Using TypeScript by default in 2021
Vitor Capretz / January 26, 2021
9 min read • ––– views
Yes, TypeScript is (still) a controversial subject to talk about in the JavaScript community, as with unit testing or automated tests in general, I still feel like people have very different opinions and experiences with both. But I've been using TypeScript in every project for more than a year and I am a strong believer in it.
TypeScript won last year's State of JavaScript award as the most adopted technology in the JS ecosystem in 2020, the interest and adoption continue to grow, and if you never tried or didn't adopt it yet, it might be time to do so.
How it started for me
You may have heard about the term "JS fatigue": when you realize that there's too much to learn in the JavaScript (JS) ecosystem and you rush to keep pace with the community and don't miss out on what everyone else seems to be talking about.
Been there, done that.
So when I decided to take it slower for my own mental sanity, TypeScript was one of the technologies I deliberately chose to scope out of the things I would spend my time learning and let it evolve, and if needed I would learn it.
The time has come when back in 2019 I was working on a React Native app with lots of Node.js microservices in a mono repo that had 100 or so developers committing every single day. The legacy code was mainly un-typed and we had a few instances of Flow and even TypeScript running here and there. We didn't have any official tooling nor guidelines, and when left up to each team to decide what they would choose, they went with the pure JavaScript approach.
We were growing fast, a few months later we were reaching 200-300 developers working in the same app and still hiring.
Some developers with previous TypeScript experience and willingness to try it out started looking for guidance, better tooling, and official support from the teams who supported the app. It eventually got enough traction, knowledge was being spread, we started understanding the benefits and we were open to taking the time in our smaller teams so we could assist whenever possible.
After months of discussing possible approaches, how we would need to improve tooling and developer experience, and a lot of knowledge sharing, the work started happening, and soon we would see many open Pull Requests where hundreds of files were being migrated from JavaScript to TypeScript.
The thing is that for it to happen I believe everyone (or most of the people at least) should be involved.
Say you are consuming services or modules from different teams and they decide not to collaborate with the migration, then a few any
typings start spreading and soon you lose a lot of the value that having a strongly typed codebase brings.
That's why I believe having started with knowledge sharing was the right step for us.
How is it going
We are around 300 developers now and I would say at least 80% of our codebase is strongly typed, I feel more confident with a change I introduce, as soon as I see the TypeScript compiler screaming at me because I'm trying to use a component with missing props without the need to actually wait for the app to build and see it as a warning in the console instead, I thank the TypeScript gods.
It's hard to reach 100% typing in such a large codebase, even tho I still strive for it and we should continue to do so, we are still building products, shipping new features, and fixing bugs.
We can't always stop the train.
It's also important to keep your eyes open, as new developers join the company they will not have the same background, so have internal docs with guides and make sure knowledge is being constantly spread.
When I see new Pull Requests where new JavaScript files are being created I ask the developer why is that. If they are doing so it might be a sign that our process is still not good enough. Did they find our docs? Was their onboarding in the company correctly ran? Does our tooling still have flaws? You get the point.
Keep looking for improvements and know it's not a one-time event. I strongly believe the benefits do pay off.
Tradeoffs
Everything in tech (maybe in life?) comes with tradeoffs, you choose one thing and you need to understand what's the cost, can you roll back from your decisions easily? Are the benefits strong enough to keep you on the same path?
Here are some of the things I personally struggle with:
1 - Support for files with the same name and multiple extensions
I spend most of my time writing React Native code in a codebase that also compiles to Web, so it happens sometimes that the same file MyComponent
will have .ios.ts
, .android.ts
or .native.ts
and then .web.ts
extensions, I am not sure if we just didn't quite find the right setup yet but navigating to those files by CMD + Click
on VSCode doesn't really work well in our huge codebase.
We have to declare a common MyComponent.d.ts
file that exports the correct typings for all platforms, which also makes it harder to split between native or web-only props a component might receive.
2 - Types can get really annoying/complicated really fast
There will be moments where you're in the flow building a cool feature, then get stuck in a type that's giving you some trouble.
TypeScript inference system works great for simple things, but try adding ramda
and using pipe
with multiple curried functions and you're lost.
There are other particular scenarios where a function might not be properly typed, then you have to use ReturnType
and hope it works.
You'll lose some time every now and then just trying to figure out the types, which will make you wonder if it's all even worth it.
3 - Barries to Entry
Adding TypeScript to your codebase will be a larger barry to entry for everyone working on your project.
It's one step more in your onboarding and a culture mindset you're going to have to train people for, that includes having more documentation and people willing to spend some more time with the new person. Or even adjusting the expectations so you're not pressuring a new developer to start delivering projects when they are still adapting to your codebase.
Hiring can also be more difficult, it's a tricky situation since one might say "make it a requirement for new candidates" and you possibly leave a lot of good people out from your interview process because they didn't have the opportunity to learn TypeScript yet.
For me, the best approach is to make it clear in the interviews that you don't expect them to know it right away, but they should be comfortable and willing to learn in the first few weeks/months when hired (that applies to React Native developers too since it's hard to find people with experience in it we often hire Web Developers who are willing to step on the native land).
4 - In the end of the day, it's still an "addon"
TypeScript is defined as a superset of JavaScript, so in theory, you keep writing your normal JavaScript code and you give it extra powers by typing it, and as with anything that is an "addon" to any programming language is that it can eventually fade away, lose its hype, support from the community and then you're stuck with it until your next big rewrite.
Yeah, this applies to anything in tech really, programming languages also die. But we do have to keep it in mind when making decisions. You get the point.
Part of a decision in betting in TypeScript was that it eventually became what seems the standard approach for the community. Remember I mentioned we also had files typed with Flow
instead? What if we bet hard on TypeScript just so it died after a while? That's one of the reasons not to jump too early in some decisions that may cost too much to revert.
Resources
Every personal project I do now start by bootstrapping it with TypeScript, and the experience is great! If you can't move an existing codebase, try starting with the new ones you're still setting up, or introduce TypeScript while allowing files in JS so there's no need to migrate all at once.
Tip: Most commands to bootstrap a project nowadays have a TypeScript template, try using them more often! Some examples are:
npx react-native init AwesomeTSProject --template react-native-template-typescript
for apps ornpx create-next-app --example with-typescript with-typescript-app
for websites.
TypeScript still has a long way to go, but I believe now we are not anymore in the "too soon" moment, it has been proven to work for many different types of projects in all sizes and the support from the community is great!
So if you haven't yet, give it a try!
At this point there are tons of resources out there so you can learn how to setup TypeScript in any kind of project, no matter if you are using Vue, React, Svelte, or even just setting up a small server with Node.js. Go to your favorite search engine and look for TypeScript + [your favorite cookie flavor]
, you'll find it.
Personally, I keep coming back to TypeScript's website since I know it will contain the most updated information.
I've been using a lot of GraphQL recently and I've been benefiting from the TypeGraphQL framework to generate typed schemas from my Back-end services that then can be shared with the applications consuming it.
Ben Awad's incredibly long and useful YouTube tutorial was also a great refresher for me on one of the ways a modern application can be built.
My good friend and one of my TypeScript mentors, @Yurick_, also recommended tsdx for when you need to start new TypeScript out of the React realm. I didn't personally use it but it might be worth it to take a look!
So, do you already use TypeScript? Do you now hate me for even suggesting it? Let's chat on Twitter so I can hear your thoughts!
I hope I gave you a nice perspective from my own experience, I know it's not the same for everyone but I'm curious to learn as well 😃
Have a great day! 👋