If you're anything like me, you use Typescript because you need to. Your first startup in 2013 had a gigantic Angular.js codebase written in pure JS, and you were a scrappy hacker who thought he could change the world by plowing through the code and single-handedly maintaining it all.
After a huge QoL refactor, you learned that the time it took was not worth the ROI and that you needed a tool. You wanted something that could solve the problem systematically but is still lenient enough for you to move fast while not being some quick annotation with arcane tooling that is not smart enough to rename your function argument.
After trying out Flow, Haxe, ReScript, Clojure... you found TypeScript. The light clicked in your head๐ก
In this article, I am going to hype the $$$$ out of TypeScript and why you, yes, you, MUST use it. Having used it since 2015, I have seen it all - slow as $$$$ script runtime, messy type collusion, enum not working as expected, and did someone mention emitDecoratorMetadata
?
But hey, eight years in the trench, why didn't I just switch to Rust, C#, Zig, Dart, or some other "better" language?
Read on.
๐ Table Of Contents (TOC).
- Ease of Learning
- Flexible Type Checking System
- Concise and Readable Syntax
- Intuitive Syntax
- Modern Tooling
- High Productivity
- Realistic Promises
- Flexibility
- Large Community
- Clean Code Made Easy
- A JS Superset
- A Compiled Language
- Reduced Tooling
- High Performance
- No Need to Write Unit Tests
- Types Are Extremely Useful
- Lower Tech Debt
- To Boldy Refactor
What is Typescript?
It is JavaScript, with optional typing, that you can refactor. The code below is both JS and TS:
const derp = "world"
console.log(`Hello, ${derp}`)
The nice thing about TS is that I can press F2 on that derp
variable and rename it, and it will work even if I did it in an external module.
Why is that? All thanks to the TypeScript AST produced by TS language server running under the hood inside VSCode. The collaboration between the language and the editor makes it do things that are impossible otherwise.
Those who have yet to experience the joy of TypeScript, simply have yet to experience the horror of "JavaScript with friends."
Should I use TypeScript?
YES.
Even for a tiny little module with 1 line of code?
Why YES:
export const life = 42
Or you can suffer with babel tooling, custom webpack configs, three separate rollup build configs targeting iife, cjs, esm, and heck, maybe WASM (assuming life
is an uint8).
If not for you, think of the consumer of your module - is life
a string or a number? The people need to know!
1. Ease of Learning.
"strict": "false"
Disable strict mode, and you will be writing JavaScript. When the static compile-time warnings bother you to a certain threshold (and they should bother you), start reading into the detail as to why the warnings are as such and fix them!
Did you know? VSCode codebase itself was not strict until Feb, 2020 [0]
2. Flexible Type Checking System.
"strict": "false"
Just disable strict mode, and you will wish it was slightly stricter. But this:
type ApiRoute = "/api/${string}"
Is an example of a flexible type system, that can prevent silly mistakes across your entire codebase.
The BubbleSort implemented purely using the type system [1], is also a good example of how flexible and powerful TypeScript is. Those who use it to claim TypeScript is "strict" missed the whole point of the demonstration.
3. Concise and Readable Syntax.
TypeScript infers type for you:
let foo = "bar" // foo is a string
But you can make it do even more:
let foo = "bar" as const // foo is strictly "bar"
foo = "lol" // -> error
TypeScript self-documents its arguments. Thus you only need to document the high-level idea of your function:
/**
* Add two numbers
*/
function add(a = 0, b = 0){
return a + b
}
add(1, 2) // 3
add(1, "0") // compile err
Utilize it wisely, and you will have a happy little codebase.
4. Intuitive Syntax.
TypeScript type syntax shares many resemblances to that of C# and C++.
To the experienced, it's quite intuitive (which explains its high adoption rate).
To those who are new to programming in general, the learning curve to some of the advanced syntax might be as high as learning C++ itself.
This explains why Python triumphs when it comes to teaching programming - it's more intuitive to most people because there are no braces. Refactoring a large python codebase, on the other hand, is a massive chore if the tab alignment is inconsistent between modules. Jupyter notebook had made it much better over the years, tho!
Just disable strict mode, you newb! - jokingly, I said.
5. Modern Tooling.
TypeScript is a compiled language. Thus, the same code can now be compiled to work on various runtimes, architectures, and systems. The drawback is, you will need to compile it OR use a runtime that runs TypeScript natively.
If TypeScript does not support a certain runtime, or if the compiler is unavailable in a certain environment, it's almost trivial to add them - use esbuild
[2].
The power of TypeScript is not about the language itself, but the result of how it is interpreted. The TypeScript AST is integrated into the TypeScript language server within the editor, which enables features such as autocompletion, module import suggestions, type inference, and cross-module refactoring.
These modern tooling features might not benefit small projects as much as it does big ones. However, big project starts small, and it's better to start with the right foundation and footing, than retrospectively add them later on.
6. High Productivity.
Just disable strict mode, and enjoy all the speed and zero friction:
- Type coercion/inference
- Cross-module variable renaming/refactoring
- Import suggestion
- API typing and type-safe API modules
- Scoped variable renaming (yes, try it with plain JS)
- Any other TypeScript features
The key productivity gained by TypeScript in an enterprise team environment is the ability to use and explore module APIs without even having to check the documentation. More so when exploring 3rd party vendor APIs.
7. Realistic Promises.
Straight from the TypeScript front page:
TypeScript is JavaScript with syntax for types.
TypeScript is a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale.
It gave me exactly what it promised:
- A typed language (optionally strong, just disable strict mode)
- Better tooling via VSCode integration, as well as tools created using and for TypeScript itself - ESBuild, PNPM, TurboRepo, etc...
8. Flexibility.
"strict": "false"
Just disable strict mode, and you are practically writing JS, but with a .ts
file extension.
9. Large Community.
Do you have a TypeScript question and need to speak to a community member? The TypeScript Discord server is very active: https://discord.gg/typescript
So is their Stack Overflow: https://stackoverflow.com/questions/tagged/typescript
This is the benefit of speaking a common language that's slightly more powerful (dynamic) than the base language. It's like the original British English vs. the Americanized English. The latter sees massive adoption due to its flexibility in accommodating different culture, meanwhile, the community that uses it continue to grow due to the sheer size of the continent that spawned the dialect.
10. Clean Code Made Easy
TypeScript makes it easier for the editor to understand your code - which is required for better tooling. This, in turn, promotes cleaner code. Experienced developers leverage these properties to organize their code to be maintainable and easy to refactor - for the editor and their team.
I often see inexperienced dev struggles with organizing their code because, more often than not, they tried to be "clever" with it. This happens in almost any language - C++, Python, Haskell, Scala, you name it. The elusive and novel ternary or pipe operator they recently learned often leads them to utilize it immediately - and for a good reason. That's how one learns the language syntax. This often happens because there is no clear guidance or clear-cut benefit perceived - likely, they did not use the tooling. I would argue it is much easier to write complex code that's impossible to debug in JavaScript (golf-style), than TypeScript.
11. A JS Superset.
TypeScript IS a JavaScript superset - just disable strict mode and ignore any compiler warning!
const star = {}
star.trek = 47
The above code "compiles" to JS, and is also valid JS. The "superset" property of TS is that it added the TS compiler warning that tells you exactly what is wrong - the original object does not have the property "trek." The warning is a "feature" of the superset property - plain JS would not be aware of such an idea.
Side note, this works:
const star = {}
star["trek"] = 47
12. A Compiled Language.
Being a compiled language, you can leverage the TypeScript AST to do some pretty cool stuff. Namely, you can use the latest ES syntax and let the compiler handle the compatibility for you, as well as optimization. Even better, it can target the output to node, browser, worker runtime, etc...
On the other hand, you can convert the typing from other languages into TypeScript AST - from Rust to TypeScript with TypeShare for example [3]. This allows TypeScript developer to consume Rust native modules with API documentation via the Rust typing itself.
13. Reduced Tooling.
With the advent of parcel [4], esbuild [1], and tsup [5], you can say goodbye to extra tooling. Use one of these bundlers, and you will have TypeScript transpiling as fast as javascript being optimized by terser. This is because these bundlers skipped the type-checking steps and went straight to transpilation.
This allows the editor integration to shine, and separate the linting steps from your building steps if you have a CI/CD pipeline.
14. High Performance.
TypeScript produces much more performant code because the benefit of using it - editor integration - encourages developers to write better, cleaner code, which is easier to optimize.
15. No Need to Write Unit Tests.
The compiler and type system catches most of the silly mistakes possible that need to be tested with unit-test. This allows unit tests to focus on core libraries, and the team can focus on E2E test - the more important one!
If you are a junior developer working under a manager who's adamant about unit tests and the 95% code coverage threshold, my condolence. You might try to convince them to disable strict mode, write your test with a TS transformer that disables strict mode, or simply write the test and add // @ts-ignore
at the top of the file - reap the benefit, ignore all the warning!
16. Types Are Extremely Useful.
When working with other people, external APIs, and overall, any distributed system that requires you to study payloads of API that you did not own - having decent (even incomplete) types will save you $$$$ and $$$$.
Try to work with the Stripe API without the typing, and deploy it to prod.
I $$$$ dare you.
17. Lower Tech Debt.
Switching from TypeScript to Rust is a rewrite, that is not tech debt.
Using plain JavaScript, with zero editor integration, resulting in inconsistent code that's impossible to refactor and maintain, is a tech debt.
Arguably, you can incur tech debt by using TypeScript if you are using it without trying to utilize the benefit of the editor and tooling integration the ecosystem provides, but why would you?
It's like using C++ without a linker. Now you must convert C++ to Assembly instead of writing a linker - is that a tech debt or the lack of tooling utilization? I'd argue the latter.
The same can be applied to any language and ecosystem - try to use Rust without Crate, Ruby without Gem. A language represents not just its syntax, but its entire tooling ecosystem.
Typescript's encouragement of clean-code erases tech debt.
18. To Boldly Refactor.
Finally, the key power of TypeScript, compared to plain JS or most web-based languages: is the ability to refactor a large codebase, with thousands of modules, with ease. This enables the codebase to evolve from small to medium, to large, with progression and iteration instead of a large wholesale rewrite.
This would not be possible without the tight integration between TypeScript and the VSCode editor. This killer combination enables module moving, file renaming, and import resolution refactoring with a click of a button.
DID YOU KNOW? There are plenty of similar code editor enhancement solutions in other compiled language. A popular one within the C++ professional community is the Tomato kit for Visual Studio - they have provided code refactoring, renaming, etc... for C++ since 2010s [6]
Conclusion
USE TYPESCRIPT Y'ALL!
References.
[0] https://code.visualstudio.com/updates/v1_43#_strict-true
[1] https://www.youtube.com/watch?v=Uf1D0GoEzlY
[2] https://esbuild.github.io/
[3] https://github.com/1Password/typeshare
[4] https://parceljs.org/
[5] https://tsup.egoist.dev/
[6] https://www.wholetomato.com/
Top comments (1)
I am curious why you decided against ReScript?