18F / frontend

18F's Front End Guild –  content has been moved to https://github.com/18F/development-guide

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add information about static type checking

toolness opened this issue · comments

I think it'd be really useful to have a section on static type chacking in the Front End Guide (#158). (Or alternatively, in some kind of general JS guide that can be used for both front and back-end JS development.)

The two big static type checkers for JS code right now are TypeScript (Microsoft) and Flow (Facebook).

Using either one of these is a great idea. Both of them are designed to allow you to incrementally introduce static typing into existing codebases, and continue programming using standard JS idioms. Their heavy use of type inference means that you don't actually have to add lots of annotation to benefit from them (i.e., using them doesn't mean your code suddenly has to look like Java).

I've found that using a static type checker:

  • vastly reduces the variety of possible states your front-end code can be in, reducing uncertainty;
  • greatly reduces the frequency of runtime exceptions;
  • allows your code to be more self-documenting;
  • makes your code editor a lot smarter and more helpful, enabling it to provide autocomplete suggestions and inline documentation (assuming you've installed the appropriate plug-in for your editor of choice).

Note that a static type checker is not a substitution for unit testing. IMO, the two are complementary and not at odds with one another.

Below are my thoughts on the two major choices.

TypeScript

  • For a really quick introduction, see my video playlist Fun with TypeScript.

  • TypeScript is a superset of JS that allows you to annotate your code with type information. You need to rename your files to have a .ts extension instead of .js, and you need to introduce a transform step in your build pipeline that removes the type annotations.

  • TypeScript also has Babel-like functionality in that it will also transform your code from ES201x to ES5 if you want it to.

  • TypeScript has a huge community of third-party type annotations for third-party libraries, though not all of them are accurate, which can sometimes be frustrating--particularly because these annotations are installed as npm modules, which makes them difficult to modify locally.

Flow

  • Like TypeScript, Flow is basically a superset of JS that allows you add type annotations to your code. However, unlike TypeScript, Flow supports an optional comment-based syntax which allows you to embed your annotations in comments. It's a bit less readable, but it allows you to quickly get started with adding type annotations to a project without having to deal with modifying your build pipeline and configuring your editor.

  • Unlike TypeScript, Flow does not have any built-in Babel-like functionality; in fact, unless you're using the comment-based syntax, you must use Babel to strip the type annotations out of your code so browsers can run it.

  • Flow's library of third-party type annotations for third-party libraries appears to be much smaller than TypeScript's. However, unlike TypeScript, the third-party tool for importing third-party library type annotations vendors them into your project, which makes it easier for you to modify them if you need to.

Oh, I also just found out that TypeScript recently added support for type checking normal JavaScript files, i.e. non-type-annotated files. What's especially cool about this feature is that it parses JSDoc comments, so if you just document your code normally, TypeScript will essentially make sure that your documentation is accurate. And contributors to your codebase won't face a learning curve of learning a superset of JS.

For reference, we've just added some TypeScript support+code to 18F/omb-eregs#804. The main reason we chose TypeScript over Flow is because we're definitely going to be using a front-end library called ProseMirror, and it currently has annotations available in TypeScript but not Flow (and in general, TS seems to have a larger ecosystem of third-party annotations than Flow, potentially owing to its age).

So far so good!

In CALC, we've taken a different approach with https://github.com/18F/calc/pull/1670, using TypeScript's JS checking to check our legacy JS. We're currently white-listing which files to check by adding a // @ts-check at the top of any files we want checked.

One really nice thing is that it basically encourages us to document our code, because the JSDoc parameters are parsed as type annotations.