Developing on Staxmanade

Spend the Effort to Make Your Tests Better Documentation

(Comments)

You may be writing tests, but are they describing the behavior well enough to know what business case it's covering a year from now?

Today's lesson or re-lesson. Don't just write your tests, write it so you can understand the intricacies a year from now.

The other day I was pairing on a what we first thought was a bug in our software. I was explaining something we saw.. "oh yea, that's a bug, oh and look at these tests, they look wrong also. Why is this so wrong? How did we not catch this last year? Something is off here... etc..."

While I had some tests to cover a business requirement a year ago when we wrote the software, I had not properly described the business case within the test to document it's purpose.

The subtle, bug-look-a-likes turned out to be proper behavior. If only I had not just documented the expected behavior via a test, but had properly describe WHY this behavior existed within the test, we could have avoided potentially breaking it (by "trying to fix it") and the test could have better communicated the WHY of this strange case.

This is just a reminder to myself to write better tests. Doing tests, great. Well documented, business explanation of the WHY in the tests? Way better!

Happy testing!

(Comments)

JavaScript - Refactoring too many function params

(Comments)

A code smell that can creep into your JavaScript codebase and quickly make the code difficult to follow is when a function has too many parameters.

EX:

myFunction("val1", 1, true, false, false, true);

Looking at the above, we can sort of tell that the first param is some string, maybe we can even tell what it's purpose is, the second a number maybe we even know why if we understand the codebase. But the booleans that follow? What are those representing? How do you know you're providing the right value for the right argument?

One approach is to refactor those parameters into variable names to help give them meaning.

EX:

var firstName = "val1";
var age = 1;
var isCool = true;
var isHungry = false;
var isSleeping = false;
var isHappy = true;
myFunction(firstName, age, isCool, isHungry, isSleeping, isHappy);

Now at least when we look at each parameter we can see it's name and that helps give some context of what it represents.

But as this parameter list grows it can be difficult to maintain. We could argue it's already too long.

What if you have to add a parameter in the middle?

How can you be sure all the callers get updated correctly?

Another approach would be to refactor this list of parameters into an object of properties.

This comes with some benefits like, you can add/remove properties without worrying about parameter ordering, as long as they can be optional and have solid defaults.

One cool thing I found with ES6 destructuring and enhanced object literals is if our function definition AND our caller follow a similar pattern. Meaning the variable names used in the caller are the same as the parameter names within the function.

EX:

function myFunction(firstName, age, isCool, isHungry, isSleeping, isHappy) {}

//**

var firstName = "val1";
var age = 1;
var isCool = true;
var isHungry = false;
var isSleeping = false;
var isHappy = true;
myFunction(firstName, age, isCool, isHungry, isSleeping, isHappy);

To refactor this we can simply have the caller pass an object, and have the function use destructuring of that object. It simply becomes.

function myFunction({firstName, age, isCool, isHungry, isSleeping, isHappy}) {}
var firstName = "val1";
var age = 1;
var isCool = true;
var isHungry = false;
var isSleeping = false;
var isHappy = true;
myFunction({firstName, age, isCool, isHungry, isSleeping, isHappy});

This is cool because it's simple, requires very little work, and now we can gain the benefits of using an object instead of an ordered set of parameters.

This opens the door to quit a few other organization options.

Happy Cleanup!

(Comments)

Using script=module to Quicky Spike Some Mocha Tests

(Comments)

I'll be honest, I secretly hoped JSPM would win the front end over and become our standard, and while I haven't truly followed it closely in the last year or so I recently tried this out and was blown away at how beautifully simple it is (at least on the surface).

Say I want to quickly run some Mocha test in a browser. Like say I'm spiking something, wanting to use tests in something like jsbin or plunkr and just get code running quickly.

Most browsers now support tye script=module tag which allows you to use import statements withing browser script tags. O_O

So how could I use this to import mocha and write some quick tests? I'm so glad you asked.

  1. Mocha's browser U.I. looks for an element with id=mocha so let's add that.
<!DOCTYPE html>
<html>
<body>
+  <div id="mocha"></div>
</body>
</html>
  1. now let's add some javascript to import mocha
<!DOCTYPE html>
<html>
<body>
  <div id="mocha"></div>
+  <script type="module">
+    import "https://dev.jspm.io/mocha"
+    console.log("Mocha:", Mocha);
+  </script>
</body>
</html>

This package is loaded using the import functionality built into our browsers now and JSPM which allows us to load some npm packages right through the browser. MAGIC!

WARNING: DO NOT do this for a production-type environment. This is just a quick prototype tool leveraging JSPM's dev hosted servers that allow us to use import to load packages via NPM through their servers. Thank you JSPM.

  1. Now we can do some browser-specific steps to get mocha to run.
<!DOCTYPE html>
<html>
<body>
  <div id="mocha"></div>
  <script type="module">
    import "https://dev.jspm.io/mocha"
-    console.log("Mocha:", Mocha);
+    mocha.setup('bdd');
+
+    mocha.run();
  </script>
</body>
</html>
  1. Let's add some tests.
<!DOCTYPE html>
<html>
<body>
  <div id="mocha"></div>
  <script type="module">
    import "https://dev.jspm.io/mocha"
    mocha.setup('bdd');

+    describe("some awesome tests", function () {
+        it("Should pass", function (){
+            console.log("passing test");
+        });
+        it("Should fail", function (){
+            throw new Error("OH NO!!!");
+        });
+    });

    mocha.run();
  </script>
</body>
</html>

THAT'S IT - using almost nothing but our browser's capabilities (and maybe a complicated JSPM back-end tool) we can easily write some in-browser tests to spike something, or just play around.

  1. But wait - this looks like meh

That's true, let's bring in some styles

<!DOCTYPE html>
<html>
<body>
  <div id="mocha"></div>
+  <link rel="stylesheet" href="https://dev.jspm.io/mocha/mocha.css">
  <script type="module">
    import "https://dev.jspm.io/mocha"
    mocha.setup('bdd');

    describe("some awesome tests", function () {
        it("Should pass", function (){
            console.log("passing test");
        });
        it("Should fail", function (){
            throw new Error("OH NO!!!");
        });
    });

    mocha.run();
  </script>
</body>
</html>

NOTE: Prob better to use a CDN version instead of pounding JSPM servers (sorry).

Final


<!DOCTYPE html>
<html>
<body>
  <div id="mocha"></div>
  <link rel="stylesheet" href="https://dev.jspm.io/mocha/mocha.css">
  <script type="module">
    import "https://dev.jspm.io/mocha"
    mocha.setup('bdd');

    describe("some awesome tests", function () {
        it("Should pass", function (){
            console.log("passing test");
        });
        it("Should fail", function (){
            throw new Error("OH NO!!!");
        });
    });

    mocha.run();
  </script>
</body>
</html>

Cake!

I've done this a few times lately, and am almost able to do it without looking up api and syntax O_O. I also don't need webpack, gulp, servers, or anything but a wee-bit of html/js and some luck (that JSPM servers will hang in there).

Happy Testing!

(Comments)

How to JSON.stringify and Order Dictionary Result

(Comments)

The other day I had the desire to serialize a simple Javascript Object and have it's keys ordered in the output.

Sorting before saving the object to a file like in approvals makes it much easier to diff two JSON documents that may not originally be in the same order.

So I threw together this quick little helper. It's far from perfect and won't suit all needs. But if all you're trying to do is sort and serialize an object it seems to be working well for now.

Happy Dictionary Reading!

(Comments)

Should I Use JavaScript Single (') or Double (") Quotes?

(Comments)

The topic of using JavaScript single ' or double " quotes comes up often enough that I thought I'd create a bit of an amalgamation of items around the topic for future reference.

Today, it came up at work when someone sent a PR to our internal standard eslint config repository and there were some various points brought up with no real final solid winner or resolution.

In this post, I'm not (sadly) going to write anything interesting or profound or even original. Just wanted to aggregate some pros/cons as I've seen splattered in various locations around the web on the topic.

The most important point or the TL;DR

  • Define one standard and stick to it. Do not use one in one file, and a different one in another file, or even especially avoid mixing quotes within the same file if possible.

Basic qualities they both share

  • They both represent strings (yay! strings!)
  • Which ever one you start with, must be the same one you end the string with.
  • There is really no difference in the end between using single or double quotes, meaning they both represent a string in the end. The system doesn't really care which one you use (but you might?).
  • No need to escape the other character within a string. So a double quoted string can have single quotes without escaping them, and a single quoted string can have double quotes within it without having to escape them.
    • "Double quotes with a single ( ' ) quote in the middle"
    • 'Single quotes with a double ( " ) quote in the middle'
  • Each type must escape their own type
    • "double quotes ( \" ) must escape a double quote"
    • 'single quotes ( \' ) must escape a single quote'
  • On German, Hungarian, Austrian, and many other keyboards, you have to use the Shift key for both single or double quotes.
  • On Turkish Q keyboards it's apparently the other way around (need <Shift> for single quote vs double).

Pros for single quotes:

  • One popular argument for single quotes is when you have to write html within javascript:
    • If you use single quotes you can write var html = '<div id="some_div"></div>'
    • If you use double quotes you must escape each nested " EX: var html = "<div id=\"some_div\"></div>" which can get annoying. Or you could use single quotes within the html string, but I don't want to cover quotes for html here (that would just hurt)...
  • Single quotes can often look better when you're using them to represent an empty string '' vs "" (too many little marks in the latter and can be difficult read - ahhh)

Cons for single quotes:

Only real con I can come up with is copying/pasting between JSON and JavaScript files - single quotes are not supported within JSON files, so you'd have to do a host of search/replace (and escaping of double quotes)...

Pros for double quotes:

  • JSON only allows double quotes (unless you control the data, and can use a library that is more liberal at parsing JSON - but a JSON file with single quotes is not truly a JSON file)
  • Most likely noobies to JS will be familiar with double quotes from their previous programming languages
  • Double quotes eliminate the need to escape apostrophes when writing english sentences.

Cons for Double quotes:

  • Must press an extra key <Shift> when wanting to use double quotes

In the end

I recommend single quotes as a solid standard. Unless you are copying JSON objects in JavaScript and pasting them into JS files a ton - it's generally my personal preference.

Some References:

Happy Quoting!

(Comments)

How to Access Two Mac Accounts at the Same Time

(Comments)

From a single Mac if you wanted to access two unique accounts at the same time, I found out through a neat little trick how to accomplish this.

This allows you to log in to a second unique Mac user while already being logged into the first account already. It can be done without having to logout/login to each one individually (one at a time).

Why would I need to do this?

The reasons could vary but here are a couple examples:

  • If you use one user for work, and one for personal to keep some separate context, but while at work maybe need to access a file or email from the personal account.
  • You'd like to access a separate iMessage account without it getting mixed into yours. Say you want to spy on the kid. (Not saying whether this is ethical or not - depends on your parenting style - just proposing a reason for using this tool).

Disclaimer

To accomplish this we're going to be turning on some services/features that have the potential to open security vulnerabilities so please use with caution and learn/know your risks.

Setup/Configuration

To accomplish this your Mac needs to have the proper permissions and configuration in place to allow this to happen.

First we need to access the system preferences:

access mac system preferences

Then open the Sharing preferences:

mac sharing preferences

Then enable Screen Sharing and don't forget to add the specific users you want to allow screen to be shared for.

Note: I blocked out this specific user-name - but assume the blacked out user is the Mac account's user that I want to log into using the Screen Sharing application

screen sharing preference

I had to enable enable remote login to allow the up-coming ssh command to run. Here is the configuration I used:

remote login preference

Startup an SSH Session

From the currently logged in session, open a Terminal and run the following command:

ssh -NL 5901:localhost:5900 localhost

The -L has this to say in ssh's man pages

     -L [bind_address:]port:host:hostport
     -L [bind_address:]port:remote_socket
     -L local_socket:host:hostport
     -L local_socket:remote_socket
             Specifies that connections to the given TCP port or Unix socket on the local (client) host are to be forwarded to the
             given host and port, or Unix socket, on the remote side.  This works by allocating a socket to listen to either a TCP port
             on the local side, optionally bound to the specified bind_address, or to a Unix socket.  Whenever a connection is made to
             the local port or socket, the connection is forwarded over the secure channel, and a connection is made to either host
             port hostport, or the Unix socket remote_socket, from the remote machine.

             Port forwardings can also be specified in the configuration file.  Only the superuser can forward privileged ports.  IPv6
             addresses can be specified by enclosing the address in square brackets.

             By default, the local port is bound in accordance with the GatewayPorts setting.  However, an explicit bind_address may be
             used to bind the connection to a specific address.  The bind_address of ``localhost'' indicates that the listening port be
             bound for local use only, while an empty address or `*' indicates that the port should be available from all interfaces.

For -N:

     -N      Do not execute a remote command.  This is useful for just forwarding ports.

Here's what it looks like when I ran it locally:

> ssh -NL 5901:localhost:5900 localhost
The authenticity of host 'localhost (::1)' can't be established.
ECDSA key fingerprint is SHA256:ytfRv5WDPuTjGbBugJjmc8gOhsHga7ozGqNgjOXpdRM.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
Password: <I entered my account/admin password>

Use Screen Sharing to login

Once that ssh command above is up and running, we're now ready to log into the other account using Screen Sharing.

Open the Screen Sharing Mac app located in: /System/Library/CoreServices/Screen Sharing.app. You can also use CMD+<Space> (Spotlight) and type Screen Sharing to open the app.

Then enter localhost:5901 to start the process.

It should look like this:

screen sharing app startup view

In the below screen entered the username/password that you want to login as. (Not the current account - the other one)

screen sharing app login view

Now select that you want to login as "yourself" where "yourself" is really "other account":

screen sharing app access user strategy view

...and boom, you should now able to use two separate accounts on a single Mac session.

Happy Spying (wink wink)!

(Comments)

How to block git commit if webpack bundle has changed

(Comments)

I sometimes write little web app utilities that are often statically hosted. But to use some of the new ES features means I need to drop in a build process that creates a bundle before the code gets checked in.

There are two parts to this.

  1. The raw source code. The ES6+7+next and all the nifty new js features I want to leverage today.
  2. The bundled es5 output.

In some of these projects it means I also check in the bundled code into git. A common use case is to be able to use github's pages feature to host this content (err bundled output) as well as the raw source.

The problem we can run into is if you make a change to the source, commit and push - nothing happened... Because the bundled code didn't get re-bundled, the github hosted pages page doesn't pull the latest changes in.

I'm a fan of using git pre-commit hooks to catch you early in the development life cycle to on things like test errors (or in this case a bundle issues).

So I came up with an example that allows me to make code changes and catch myself from committing when the raw source has changed, but the bundle did not reflect that.

So what is this thing?

The gist is it's a .js script that runs a set of actions and tests for the bundle.js currently vs what's about to be committed. Failing to commit if the current bundle doesn't match what the previous bundle is... Meaning, when we run our build (webpack in this case) if the bundle.js didn't change, we can commit.

This ensures that whatever bundle.js is committed is tied to the code-change the original source. Avoiding "fixing" something in the source and it not actually getting deployed because the bundle is out of date.

First get a pre-commit tool

There are some good options in the npm/node world for pre-commit hooks. Check out husky or pre-commit. However you get your precommit hook setup - great...

In my case I used husky and here are the relevant bits to my package.json.

{
  ...

  "devDependencies": {
+    "husky": "^0.13.4"
  }
  "scripts": {
+    "precommit": "node ./pre-commit-build.js"
  }
}

The pre-commit-build.js script I used

The below is the short, but complete pre-commit script I use to enforce this workflow.

var crypto = require('crypto');
var fs = require('fs');
var exec = require('child_process').exec;

var bundleFileName = './dist/bundle.js';

var getShaOfBundle = function () {
    var distFile = fs.readFileSync(bundleFileName);
    var sha = crypto.createHash('sha1').update(distFile).digest("hex");
    return sha;
}

// make sure we only bundle/build what is staged to get a proper
// view of what will be committed
exec('git stash --keep-index');

// Get a snapshot of the original bundle
var beforeSha = getShaOfBundle();

// run our build
exec('./node_modules/.bin/webpack');

// snapshot the bundle after the build
var afterSha = getShaOfBundle();

// reset anything that was stashed
exec('git stash pop');

if (beforeSha !== afterSha) {
    throw new Error("Need to bundle before committing");
}

Now whenever I make a change to the raw source code - this pre-commit script makes sure that the dist/bundle.js is correctly mapped to the raw source.

Happy committing!

(Comments)

How to Download and Convert an Image to Base64 Data Url

(Comments)

Today I was playing around with a side-oss-project and had the desire to take an image from the web and base64 data encode it. While I'm sure there is a ton written out there, I didn't immediately find the specific steps in a snippet of code. (Also, I can't say I looked very hard).

So what does any programmer do when he's not satisfied with what he can't find? He writes his own. Now that I've put it together I'm just going to post this here so I can find it again down the road when I need to. :)

Below is a utility function that I threw together that will take an imageUrl parameter and will return through a Promise a base64 encoded image data string. You can see from the example usage below that we're just setting an HTML image .src property to the result of this function and it should just work.

NOTE: also if you look at the code that accomplish this below, it may look a bit like "futuristic" JavaScript right now. With all the async/await, arrow functions, http fetch and all, but the cool thing is you should be able to just copy/paste the below into a JSBin/Plnkr/Codepen without issue (in Chrome). No need for Babel/TypeScript/transpiler if you're just prototyping something (as I was). Don't rely on this to work in all browsers yet but I'm sure when I'll be googling myself for this snippet in the future, this should work in most browsers so I'll just leave this here for now.

async function getBase64ImageFromUrl(imageUrl) {
  var res = await fetch(imageUrl);
  var blob = await res.blob();

  return new Promise((resolve, reject) => {
    var reader  = new FileReader();
    reader.addEventListener("load", function () {
        resolve(reader.result);
    }, false);

    reader.onerror = () => {
      return reject(this);
    };
    reader.readAsDataURL(blob);
  })
}

An example usage of the above:

getBase64ImageFromUrl('http://approvaltests.com/images/logo.png')
    .then(result => testImage.src = result)
    .catch(err => console.error(err));

As an alternative to base64 encoded FileReader approach above, you can also also use the URL.createObjectURL return URL.createObjectURL(blob);

There's of course a number of online tools that do this for you already.

Hope this helps future me find the implementation a min or two faster some day.

Happy Encoding!

(Comments)

Porting a Large JSPM BabelJS project to Typescript

(Comments)

I've been working on a project for over a year now that was originally written in ES6 with (some async/await ES7) using BabelJS to transpile and really enjoying the experience of using the latest javascript.

ES6/7 was great at the beginning, when I had 1, then 2... then 5 files. The project was small, I could pretty much load the entire application into my own head at once, reason, tweak, plow forward.

It didn't take too long before the project grew beyond a single load into memory. Now I'm mentally paging out components from different files as I work on various sections of the application.

Just like anything, once the project grew to this point, it became a little more difficult to maintain. Now, I consider myself a fairly solid developer, and that's likely how I made it this far without a compiler as my components were small, surface areas tight and the interactions between them were well managed. I also had a decent number of in-app unit and integration tests because generally (but not always) I'm a test-first kind of guy.

However, that didn't stop me from breaking things, making mistakes or just out-right screwing up a javascript file here and there along the way.

While working on this project, it always niggled me that the project would keep growing without the ability for the most basic of unit-tests to run (the compiler). Almost a year ago I even remember trying to use Typescript but using it with JSPM and without having VisualStudio Code all together, it just never came together (or I just didn't try hard enough).

But this past week, I gave it another go, and while I'm not totally there (or where I'd like to end up), I'm quite happy with the results I've made so far and am impressed and quite happily working in a project that has completely been ported to Typescript from ES6/7 using BabelJS.

First some idea about the project.

Now, when it comes to large software projects, I'm pretty sure I shouldn't be calling this project a "large" as the subject of this post seems to label it... But for a system built only by me in some nights and weekends, it is the largest single app I've built alone, so that's where I'm defining "Large".

The project has just about a hundred javascript files/components/classes/modules and comes in just above 12,000 lines of code. That's not counting of course all the dependencies pulled in through JSPM (using both NPM and Github). In fact I really need to look at my dependencies and see where I can trim some fat, but that's not the subject of this post.

Porting from Babel to TypeScript

With some context about the project this is coming from out of the way, I thought it would be helpful to outline the steps (or stumbles) I took along the way to get my project up and running using TypeScript with JSPM.

Pre-migration steps

Below are steps I took to get this thing going. I doubt they're perfect or even apply to your or anyone elses projects, but here's hoping they're helpful

  1. In a fresh temp folder, I used the jspm init command to setup a fresh new project and selected the Typescript transpiler option.

this allowed me to inspect what a "fresh" project from JSPM would look like with Typescript setup.

  1. The next thing I did was review the angular getting started guide to see what Typescript specific configurations they used.

Now, my project isn't Angular (it's actually React based), but I thought I could learn a little something along the way. I don't know if I actually gleaned anything while doing this (as I'm writing this post a ways after I actually did the work, but as an FYI, you might learn something reading it)

What steps did I take to port the project?

Looking back at the series of commits during my port, here's basically what I did. In some cases order doesn't matter below, but I left this list in the order of my projects git commit log.

  1. Renaming each file with the .jsx extension to .tsx (Typescript's variant of JSX) (note: not renaming anything but code I wrote - so don't touch anything in jspm_packages or node_modules folders etc.
  2. jspm install ts <-- installing the Typescript jspm plugin
  3. Updated my jspm.config.js transpiler flag with the following:
-  transpiler: "plugin-babel",
+  transpiler: "Typescript",
+  TypescriptOptions: {
+    "tsconfig": true // indicates that a tsconfig exists that should be used
+  },

Then I updated my jspm.config.js's app section with the following.

   packages: {
-    "app": {
-      "defaultExtension": false,
-      "main": "bootstrap.jsx",
-       "meta": {
-        "*": {
-          "babelOptions": {
-            "plugins": [
-              "babel-plugin-transform-react-jsx",
-              "babel-plugin-transform-decorators-legacy"
-            ]
-          }
-        }
-      }
-    },
+    "app": { // all files within the app folder
+      "main": "bootstrap.tsx", // main file of the package (will be important later)
+      "format": "system", // module format
+      "defaultExtension": "ts", // default extension of all files
+      "meta": {
+        "*.ts": { // all ts files will be loaded with the ts loader
+          "loader": "ts"
+        },
+        "*.tsx": { // all ts files will be loaded with the ts loader
+          "loader": "ts"
+        },
+      }
+    },
  1. Created a tsconfig.json file
{
 "compilerOptions": {
    "target": "es5",                /* target of the compilation (es5) */
    "module": "system",             /* System.register([dependencies], function) (in JS)*/
    "moduleResolution": "node",     /* how module gets resolved (needed for Angular 2)*/
    "emitDecoratorMetadata": true,  /* needed for decorators */
    "experimentalDecorators": true, /* needed for decorators (@Injectable) */
    "noImplicitAny": false,         /* any has to be written explicitly*/
    "jsx": "react"
  },
  "exclude": [   /* since compiling these packages could take ages, we want to ignore them*/
    "jspm_packages",
    "node_modules"
  ],
  "compileOnSave": false        /* on default the compiler will create js files */
  1. Renamed *.js files to *.ts. (Similar to step 1 above with jsx -> tsx but now just the plain JavaScript files)
  2. In all of my source code where I used to do this: import foo from './foo.js' I removed the .js extensions like import foo from './foo'
  3. I did NOT remove the .jsx extension in my import statements - but renamed them to tsx so import foo from './foo.jsx' became import foo from './foo.tjs'
  4. Next I added a file at the root of my client project called globalTypes.d.ts, this is where I could hack in some type definitions that I use globally in the project.
  5. Then I started adding my type definitions...

I used the typings tool to search for TypeScript type definitions. And if I found one, I would typically try to install them from npm.

For example: searching for react like typings search react shows me that there is a DefinitelyTyped version of the type defs and I now know that we can use NPM to install them by typing npm install --save @types/react

So I installed a ton of external library typings.

  1. Next, started looking around my editor VisualStudio Code in hopes to see a bunch of typing errors reported, and was surprised to see very few. No, not because I'm so good at JavaScript that my TypeScript was perfect. Far from it... The problem I had was the tsconfig.json file was not at the root of my project (was at the root of my client site) - but it was nested several folders down from the root of my project. For some reason the editor wasn't picking it up until I opened the editor from the location the tsconfig.json file was rooted, things didn't work.

Honestly, I don't know what the above was about - but was something I ran into. I can't say for certain if it is still an issue - I think I'm starting to see editor features load up regardless of what folder I open things - so your mileage may vary.

  1. Once the TypeScript editor features started lighting up in VS Code, my next steps were start to take the TypeScript's feedback and implement either typing work-arounds or fixing actual bugs the compiler found.

THE END - ish

Where am I now?

The above steps were really all I went through to port this project over to TypeScript and it was relatively seamless. That's not to say it was simple or easy, but definitely do-able, and worth it.

It's been a few weeks since I ported the project to TypeScript and I'm really kicking myself for not doing it sooner.

The editor assist with intellisense of function calls from internal and external modules and their usage/function signatures saves time researching external documentation.

Other observations since the move.

  1. Builds seem to be a little faster with TypeScript than Babel. I can't say I can prove this. I didn't do any actual tests on this, but just a feeling I got after migration.
  2. Sourcemaps seem to actually work. Whenever I used BabelJS, debugging and stepping through async/await it just never seemed to line up right for me. This was likely user-error or in-proper configuration of babel on my part, so who knows... but having working source-maps is AMAZING, especially with the async/await feature.
  3. One area of concern that I haven't yet worked through. Is the JSPM typescript loading up in the browser - or running jspm bundle app at the command line doesn't report any typescript errors - or fail any builds. However, I'm glad it doesn't because something isn't quite rite with my configuration as every import of a .tsx file reports an error. So, for now I'm just relying on the red squigglies in my VS Code editor to help me catch typing errors.

If you go for this port in your own project, I hope this was helpful, and that your port goes well.

Happy TypeScripting!

(Comments)