All JavaScript projects should be TypeScript projects
The Problem
The problem with JavaScript isn’t '' + 1 === '1'
, or it’s lack of multi-threading, or even the ump-teenth libraries in circulation.
The problem with JavaScript is it’s loosely-typed nature that forces developers to know the implementation of a function before it can be called. For example, consider the following code:
// lib.js
const add (n, m) => n + m
...
// mycomponent.js
const printMyResult = (n, m, o) => console.log('result', add(n, m), o)
Seems trivial right? But how confident are you n and m in printMyResult are numbers? That they’re never undefined? Are you prepared to track down all 50 calls to printMyResult?
Pretty soon your domain logic is littered with null checks and you’re throwing errors or creating overly complex method return types, which requires more type checking ad inifitum.
Even if you’re confident now, how confident will you be in six months? Or the new team member reading the code for the first time?
It doesn’t matter how many unit tests you write or how badass the VSCode plugin your coworker showed you is, you will eventually call printMyResult
with a string or undefined or something. Even if you’re cool enough to log client-side errors, good luck debugging that one at 3AM on a Wednesday morning.
The Solution
TypeScript is a JavaScript preprocessor created by Microsoft that, among other things, performs a type-checking compilation step to catch bugs before they hit prod.
TypeScript allows you to specify the target compilation version, so you can use object destructuring and spread operators and compile down to whatever arcane version of JavaScript IE11 still uses.
Installation on existing projects can literally take seconds, npm i -D typescript && touch tsconfig.json
. Config options like allowJs
let you plug typescript seemlessly into existing apps without substantially changing the development process.
In our trivial example above, you can specify the expected types or even if a param is optional
const add = (n: number, m: number) => n + m
...
const printMyResult = (n, m, o) => console.log('result', add(n, m), o)
Typically, you’ll compile TypeScript files to an outDir
that js files would read in. Even easier to incorporate into a project using Webpack - just drop in the ts-loader plugin and let the builder do the heavy lifting.
Is it possible we still call printMyResult
with a string? Sure, especially in our integration points or accepting user input. There will always be unavoidable type checks in a dynamically typed language, but they remain at the clear seams between our presentation and domain layers.
Better Example
The first example is admittedtly weak. In no world do 2 one-liners demand the overhead that comes with type-checking and a compilation step. If you’re building an app like then (like all birds) you’re probably not real..
export const MyHeader = ({ text, fontSize }) => (
<h1 fontSize={fontSize}>{text}</h1>
)
export const App = () => (
<>
<MyHeader fontSize="16px" />
</>
)
If you’re building React components in vanilla JavaScript, you’d have to actually render the app to notice you’re missing text and your fontSize is an unsupported format. Maybe you write e2e tests for literally every page element, but I do not. Maybe you have dedicated QA that drank their coffee this morning and know exactly what fontSize the element should be. You’re operating with the hope that you or someone around you will notice bugs.
Now consider the TypeScript equivalent:
export const MyHeader = ({ text, fontSize }: { text: string; fontSize: 'sm' | 'md' | 'lg' }) => (
<h1 fontSize={fontSize}>{text}</h1>
)
export const App = () => (
<>
<MyHeader fontSize='lg' text="Welcome to the Thunderdome" />
</>
)
If you leave off text? Compilation error. If your font size isn’t an expect format? Compilation error.
It’s a low-lift addition to elevate your JavaScript projects into something that isn’t spaghetti after 6 months. If you have to use JavaScript for your client or server side applications, then please consider some safeguarding against yourself and add TypeScript to all future projects.
As always, thanks for reading. - Ian