DEV Community

loading...

Seven lessons I wish I learned earlier about Typescript

chrisdhanaraj profile image Chris Dhanaraj Updated on ・6 min read

By now, you may have seen the blog posts about TypeScript's ascendance. It came second in languages developer's love in Stack Overflow's annual developer poll, spiked to the seventh most used language on Github in just two years, and has seen a steady increase in Google trends while JavaScript stays more or less stagnant. With all that, it's maybe not a surprise that where I work (Netflix Studios - we're hiring!) made an announcement last year that all our official UI libraries would be in TypeScript going forward.

The only problem was, well, I was writing one of those libraries. And I had never used TypeScript before, much less any typed language at all (or... actually, any other language beyond HTML / CSS / JavaScript). So for the last year, I've been struggling through concepts like "generics" or "type inference" and wanted to roll up a list of things that I wish I knew before I started.

1. TypeScript is a separate skill to learn and comes with all the heartaches and headaches of learning any new thing. For most of us, it will take time and persistence - and that's okay!

Something lost in all the euphoric tweets about how TypeScript will save JavaScript is simply how hard it is for someone new to pick up. I have a gut feel that a lot of the folks proclaiming how TypeScript made Javascript makes sense are coming from another typed language.

I, on the other hand, simply didn't even know the vocabulary of typed languages at all, much less TypeScript. It was incredibly frustrating to just try to sit there and google the problem I was having (and then add "typescript" to the keyword list) and not even know how to describe the problem I was having or what word to use. This frustration especially hit hard when I knew I could solve the problem with just JavaScript, but couldn't figure it out with types. It took me six months before I settled into a headspace that recognized how difficult this was and stopped beating myself up about it.

2. Typing libraries is a different skill set than just using types, and TypeScript + React is yet another skill set to learn. Look for specific examples and documentation in the layer you're on, not just generic TypeScript content.

A problem I kept running into was that a lot of the tutorials and documentation I saw assumed that you were writing an application. However, what I found that typing a piece of library code required significantly more complicated types - many things needed to be generic or much more flexible than the strong opinions you can hold in application code. You're forced to learn about generics, conditional types, and a litany of other TypeScript functionality you probably don't need in most applications. Find examples that match the work you're doing.

3. Abandon the official docs ASAP.

The official docs thankfully got an update right before I published this and is significantly easier to navigate, but still pales in comparison to a litany of other resources that will help you get started faster. If you're brand new to types, I'd highly advise you check out one of these two resources. Basarat's guide to TypeScript is a great all-encompassing walkthrough of what types even are, and then Shawn Wang's React TypeScript cheatsheet will kickstart your learnings of how to use this with React.

4. Learn and leverage utility types, and don't be afraid to explore type helper libraries.

When I first started, I didn't spend too much time thinking about how to use helper methods like Pick, Omit, Required. To make a comparison to Sass, discovering and using these methods is like finding nested media queries for the first time. Instead of all this inane repeated code, you're now just cooly relying on things you've already defined; your future self will love you when you have to refactor your code and only need to change things once.

However, sometimes you need even more power - and luckily, there are a few packages out there that the community has built to ease you on your way. Exploring these packages gives is a helpful reminder about all the things TypeScript can do, once you've mastered the syntax.

5. If it's too complicated to type, you might be running into a design error with your API.

There comes the point where you're going to throw your hands in the air and declare something impossible to type. There are too many relationships between different sets of data, the syntax is too complicated, the generics aren't working out, or some other problem in that vein.

When this happens (and it will), I'd tell my younger self to step back and reexamine the design of the function I'm writing. If it's too hard for me to accurately describe what a type is for a function, it's probably too hard for someone else trying to use the same function to intuitively know what it means.

This advice comes with a grain of salt - sometimes the issue is that you don't know enough about TypeScript yet (often, these complex types require advanced knowledge around conditional types or something similar), which was definitely the case for my first few months. However, as you continue to explore Typescript, you'll get a better sense of when it's your lack of knowledge, or when it's your API design.

6. Type guards are just functions that return true/false for an expression

This might have been obvious to other people, but for me, the words "type guard" seemed a little mysterious. Why would I intentionally run an extra function to check for types when I'm already telling TypeScript what I'm doing? The answer is two-fold.

The first is that, while you might be typing everything correctly, TypeScript can only check things that you write. Unless you generate types for external data (like your APIs), those requests can come in any form and break your application at runtime. If you have a type guard in there, you can at least capture the error and try to gracefully handle it in your UI.

The second is that type guards allow you to narrow types inside a function. Sometimes you'll pass a function an item that could be a variety of different types (generally through a discriminated union), and your function won't know which one of those types the item is. With a type guard, you can tell TypeScript which one of those items it is.

7. Generics are great and will make your components flexible. But also, ignore that terrible convention of using single letter generics.

Finally, I wish my younger self was not so scared of generics when I was starting out. Part of this was that I would read documentation and tutorials that looked something like function Foo(S, T extends keyof S) and it looked like absolute gibberish to me.

After some time, though, it dawned on me that generics are just a mashup of variables and function arguments, transmogrified into a type system. Like variables, they can be reused after they're defined to refer to their value. And like function arguments, your users are passing them in expecting that they'll get used to help compute something else down the line. Like a function argument, you can set a default generic to help your user, and because this is types and not actual values, you can also require a specific shape.

Oh - and younger me? - remember that setting a default generic does not set a type shape, you still need to extend a type to do that.

Whew, that was a lot!

Thanks all for reading! If you want to hear me and Una Kravets talk about this blog post while I was writing it, give us a listen on toolsday. If you have any questions or thoughts, feel free to ping me at @chrisdhanaraj on Twitter or drop a comment below.

Glossary

If you were like me, then some of the words I've used in this post might not have made sense. I've compiled a list of the TypeScript specific words that I referenced and some links to better understand them.

  1. Conditional Types - Conditional Types in TypeScript

  2. Generics - TypeScript Generics Explained

  3. Utility Types - List of out of the box Utility Types

  4. Typeguards - Make types real - the typeguard functions

Discussion (11)

pic
Editor guide
Collapse
stereoplegic profile image
Mike Bybee

Something lost in all the euphoric tweets about how Typescript will save JavaScript is simply how hard it is for someone new to pick up.

Been saying that for years, often while using TS and trying to guide junior devs with it.

I have a gut feel that a lot of the folks proclaiming how Typescript made Javascript makes sense are coming from another typed language.

Said that over and over again too. And that's why I think it's detrimental to learning actual JS when imposed on junior devs too early.

Collapse
chrisdhanaraj profile image
Chris Dhanaraj Author

Yep, totally agreed! I view Typescript as just another skill to learn on top of JavaScript, as opposed to a straight replacement. You're never going to be guaranteed that you'll always be working in Typescript codebase, and the fundamentals are always critical.

Having said that, I'm also mindful that a lot of job postings these days (even for "junior" devs) are sticking Typescript in there, so I totally get the drive to learn it.

Collapse
aritik profile image
Ambadi Ritik

Like you said , how typescript is touted to be something that is supposed to make JavaScript finally make sense.
What if javascript makes sense to me as it is? I did hate the language earlier but I absolutely love using it now. Don’t see any reason why I should have to learn typescript.

Collapse
chrisdhanaraj profile image
Chris Dhanaraj Author

Hmmm, to answer "why should I learn Typescript," I think for me it boils down to two things

  1. Typescript is (not to discount actual docs) the easiest way to tell team members what a function / component / piece of code is supposed to take in and do. When using a helper function your teammate wrote and typed, it's suddenly so easy to figure out what to pass into it without having to jump somewhere else. Staying in that flow state makes writing applications much much easier when everything is properly typed.

  2. There's a class of bugs (I passed in the wrong parameter! I used a string instead of a number!) that simply doesn't happen in Typescript. The compiler will throw an error for you and you can correct it before it gets there.

The first is the most important to me but it's caveated that it works best when there's a full buy-in to Typescript. Partially typed code still makes you jump around to figure out what's going on, and you don't get the same feel. It's also much more important when you have a bigger team! If it's only you writing an application, then maybe the drive for this Is much less. Although, you may do something like me where I'll begin a side-project, abandon it for six months, and then have no idea what I was doing before. Typescript could come in handy there!

The second is important just for general ergonomics; the first time Typescript tells you, "oh hey! this function expects an array and you only passed a single item" is a nice lil rush.

With all that, Typescript still means you're investing time and energy to solve those two problems above - so IMO if you're not having them or they're not super important to you, then I don't think it's worth your time!

Thread Thread
stereoplegic profile image
Mike Bybee

This is one of the more objective defenses of TS I've seen, so thank you for that. With that said, I believe it's more important to teach junior devs proper commenting in JSDoc, and ESLint can catch those same errors if set up properly.

As I commented recently in another TS article, the typeof keyword is just one example of the confusion that awaits juniors still trying to learn JS proper when you impose TS on them. And while catching type errors is clearly important, I'd argue that they need to understand JavaScript's dynamic typing first and foremost.

Thread Thread
chrisdhanaraj profile image
Chris Dhanaraj Author

Yep, 100% agreed that pure juniors would get more out of learning JS proper first and move on after. There's only so much your brain can soak in at once, and I don't equate this to learning JavaScript first vs jQuery/React/Angular/library where the latter can sometimes give beginners a rush of "hey I built something" and help spark learning.

But hey - TypeScript code can definitely give you that feeling of "hey look how well organized my code is" and maybe that does it for someone. Especially if you're moving from a different typed language, maybe it makes more sense to you than raw JS and you can back you way in after.

Collapse
jwp profile image
John Peters

I am a Typescript advocate, who also loves JavaScript, I am fluent in both styles. I do understand your frustration as I recall my first few months in JavaScript after 10 years in Java and C#. Just like you described, I was highly irritated that things I knew how to do in Java or C#, were impossible for me (at first) to do in JavaScript. I didn't even know how to ask questions that made sense to JavaScript people. For example why is it when I console.log a JavaScript object it shows all the properties and values, but when inspecting the object at runtime it only shows [object, object]. Wasn't there any way to use reflection on the object to find property values and names? Only later did I learn about Object.keys and values.

However there are some attributes to TypeScript that are interesting

  • Any filename.js file can simply be renamed to filename.ts and it's now a typescript file.
  • It should work if there are no errors in the code.
  • This means that nobody has to become fluent in Typescript immediately, they can pick it up a little bit at a time.

The parts you mentioned on TypeGuards and Generics are a bit more advanced for new folks and are not immediately required unless your company demands it.

My summary on Typescript is that it's nothing more than annotation. E.g.

// the type of person follows an interface definition or class definition.
// even it getPerson only returns a non typed object.
let person :Person = getPerson();
person.firstName = "FirstName";
person.MiddleName = "Middle"
// This is flagged as an error while typing, opposed to runtime.
person.LastName = 504;

// A class is the same thing as an interface definition except it allows initialization!


class Person {
lastName:string;
firstName:string;
middleName:string;
}

I suggest learning it slowly. It does save time after you know it as runtime errors are cut in half. Plus intellisense auto discovers APIs as we type.

Collapse
weedshaker profile image
weedshaker

The only weak point of TS is that it requires a compiler and Typeguards, which are just plain JS anyways. At least they improved the compiler. Although, the future after IE11 is without compiler black boxes eg. Webpack, so I hope. And then what’s left is inline jsdoc types, which works fantastically! 🤗

Collapse
weedshaker profile image
weedshaker

I don’t know it ether but personally I like it as simple as possible like in the good old days of JS: github.com/Weedshaker/event-driven...

Collapse
lexswed profile image
Lex Swed

I'm so glad you shared this. Thank you!
We're aiming to introduce TypeScript to our codebases as well for many reasons, and it's very useful to know what engineers don't know they don't know yet.