Why I'm "All In" on TypeScript
- 4 minutes read - 803 wordsI’ve added TypeScript to several projects I’ve worked on. In this post, I’d like to discuss why I think TypeScript is essential and document my expectations around it.
What Is TypeScript?
TypeScript is a type-safe superset of JavaScript developed by Microsoft. JavaScript is a dynamic language and doesn’t have type-safety. But with TypeScript, it does!
It’s also a gradual type system, so one file in a codebase can be converted from .js
to .ts
, and with a server or process restart, type-checking is performed on that file.
In React apps, it runs on your development server, and so all code is transpiled to JavaScript, just like JSX. The type checks can be added as a pre-commit hook or CI build step.
Why Should We Use It?
Here are my arguments in a favor of TypeScript!
A caveat is that empirical studies on type-safety remain limited. I don’t think any of the arguments that follow are a knockout punch, but together, they relate a half-decade of experience that has cemented into a strong preference.
First, I want to bet on the winner. TypeScript is popular and has a network effect. Its ecosystem is well-supported, with extensive tooling, libraries, and community adoption. TypeScript has become the de facto standard for frontend JavaScript. Teams looking to attract top talent will find that many experienced JavaScript developers expect TypeScript.
And as my colleague Josh Branchaud pointed out, the more the community adopts TypeScript, the better the entire community gets. Because my router library is statically typed, I know its exact interface when I use it, right in my text editor. This is far better than relying on documentation or source-diving every interface function I use.
Second, I’ve found that type-safe codebases are a joy to work in because so many bugs are caught in the development environment, where they are easy to find and fix. In codebases without type-safety, these same bugs are caught in test, QA, or by customers in production.
Third, I think of type-safety as more than a build tool: it’s a layer of automated testing. It adds confidence by documenting and enforcing interfaces. Automated testing is lacking in most frontend codebases I’ve worked in. Even in the best ones, TypeScript adds value.
What Are the Downsides?
The main argument against TypeScript that I’ve heard is it’s hard to learn. If you’ve never written type-safe code before, I agree! But it’s now an established tool, so there are tons of resources and examples of TypeScript code just a search away. And it’s gradual, so you can learn it at your leisure.
A second argument against TypeScript could be that you’ll write code more slowly. That could be true depending on your familiarity. After five years of writing React TypeScript, I find my development speed is just as fast as when I wrote JavaScript. And, writing code is a fraction of the software life-cycle. When you consider the time spent debugging, maintaining, and extending your code, type-safety starts to reveal its long-term value.
How Do I Expect It Will Be Used on My Teams?
In legacy frontend projects I work on, if the project doesn’t support TypeScript, I’m going to advocate for it. I intend to write TypeScript for most new code files.
As an engineering manager, I’d like any future work in such a codebase, especially edits to files that have been associated with bugs, to be converted to TypeScript.
When converting files, start with utility code, shared code, and library code. Such files tend to touch a lot of other places, so there is a big “bang for the buck.” Ideally, we don’t have TypeScript files that are importing JavaScript files, so every TypeScript file is type-safe in its own world. Start with the files that don’t import any other files and work outward. Small isolated components are also candidates.
Also worth noting: type-safety in a gradual system is exactly as good as how far we extend it. For example, I can say that my function accepts a string argument, but if the component that calls that function is not yet written in TypeScript, the transpiler can’t enforce that rule, in that specific case. This is a limitation of gradual type systems. Typing the isolated utility function still has value because it’s communicative and moving toward full adoption.
Because TypeScript allows implicit typing, we want to add types only when the transpiler tells us we must. An exception to this library code; I’ve written about the value of explicit types there.
How Will I Use It?
I plan to extend TypeScript to all new projects and open-source work that I do. It’s become a sensible default for me.
It’s easy to get started, too: most generators now include TypeScript as a first-class option so it’s easy to create new projects that transpile TypeScript.