Types are a Good Idea. Computers are relentless at finding errors, humans not so much. You can get away without using types, but large projects and teams will run better with them.
Coming from the React ecosystem, figuring out how TypeScript integrated into a project was unintuitive. I tried to fit it into my existing model of tooling, but it didn’t quite work. Here’s how I think of it now:
TypeScript is an ES6 transpiler, type-checker, and module transformer. It can be used in place of Babel, Flow, and Browserify.
Out of the box, TypeScript is more on the monolith end of the spectrum and wants to be most of your toolchain — but you can configure it otherwise, which helps us integrate into an existing project.
Let’s say we want to add some TypeScript to an existing React app, and our app is currently built with Webpack and Babel.
This isn’t the only way to migrate your code, the whole subject is rapidly evolving, but it may spark some ideas. Let’s walk through the mechanics of how this happens.
We’re only going to TypeScript-ify code unrelated to React. TypeScript is very handy for React component definitions (you get compile-time checks to ensure your props and state are valid), but it adds a bit more tooling that’s beyond the scope of this article (external type definitions). One of the benefits of moving your app over piecemeal like this is you can avoid adding such tooling complexity until you’re ready.
Here’s our pre-existing toy app (you can find the source on Github):
Our Webpack config:
Finally, our build script looks like:
To add TypeScript, we install it via NPM:
$ npm install firstname.lastname@example.org --save
TypeScript’s compiler configuration lives in a file called tsconfig.json; we create that and configure it like so:
allowJs is the option newly available in 1.8. The TypeScript compiler will run a quick sanity check on .js files for syntax errors but otherwise passes them straight through to the output directory. The “es6” options mean that TypeScript will emit ES2015-compatible modules and code, instead of transforming them.
Note that we specified a “tsDist” output folder (ourDir). We need to tell Webpack to read from this folder, not the original “src” version:
Accordingly, our “build” script needs to change:
The folder naming conventions here aren’t necessarily a recommendation for what to do on your project, it’s very much up to you.
$ mv src/User.js src/User.ts
When we build, we have a problem:
$ npm run build
src/User.ts(3,10): error TS2339: Property ‘handle’ does not exist on type ‘User’.
It’s alive! One of TypeScript’s checks is that all properties of this must be declared. We can fix that pretty quickly:
We can now build safely:
$ npm run build…Hash: 923de2cd435a90a150ce
Version: webpack 1.12.13
Asset Size Chunks Chunk Names
out.js 679 kB 0 [emitted] main
+ 160 hidden modules
Congratulations! This is a pretty trivial example, but you can imagine how it would benefit a larger project. We can gradually increase the percent of code covered by TypeScript and enjoy compounding returns.
Before TypeScript 1.8 it was a pain to migrate a codebase, but now there’s a first-class path forward.
The code for this writing is on Github. Leave notes or responses if you have questions!