Full-time TypeScript educator. Ex-
@vercel
,
@statelyai
. Used to be a voice coach. He/him. Author of Total TypeScript 🧙 Hire me to teach your team TypeScript!
I'm thinking about a pivot.
Social media kind of sucks. I have to lower the quality of what I post to fit the algorithms. I feel stymied.
So, I'm going to make the best newsletter I can. Off-platform. Interactive. Mind-blowing.
Sounds good? Come along:
🧵 The Ultimate TypeScript Thread 🧵
Here's everything I've learned from leading TS dev teams and working on XState's core team.
My goal is to turn you into a TypeScript wizard.
And yes, this thread is EVERGREEN - I'll add at least 3 more tips a week 🚀
Let's get started.
Want to learn TypeScript for free?
Here’s every piece of free content I’ve put out over the past 6 months, in order from beginner to wizard-level.
Mega-🧵
Getting somewhere with a TS error translator... Send me your mad typescript errors (full text via gist or playground) and I'll see how my system handles them.
Use Zod to parse your environment variables once, then use that inference to type process.env throughout your app.
Also, a beautiful example of how you can extend an interface from a VALUE, not a type.
🔥 TypeScript Error Translator for VSCode 🔥
Tired of TypeScript errors? Translate them to human-readable language right in your IDE.
🪄 Download the extension:
🖥️ Or try the online playground:
OH MY GOD IT'S HAPPENING
In TS 5.5, type predicates will be inferred automatically from functions that return a narrowing statement.
No more 'val is string' to force TypeScript's hand.
@danvdk
, I can't believe you got it merged. Incredible work.
This week, Total TypeScript crossed $1M in sales.
Not all of that goes to me - I've partnered with an amazing team.
But enough of it does that it's completely changed my life.
Thanks for being a part of it, folks ❤️❤️❤️
I was today years old when I learned you can do CMD-SHIFT-L to select all occurrences of a piece of text in VSCode.
How many hours have I wasted repeatedly hitting CMD-D 😬
satisfies in TypeScript has been out for a little while now.
Overall, it's been a success - but it's starting to cause some confusion.
Let's clear it up.
TypeScript WASN'T invented to add types to JavaScript.
It was invented because, 10 years ago, the tooling for JS was awful. No autocomplete, no easy refactors, no IDE errors.
TypeScript exists to make your tooling better. Turns out, types were needed to make that happen.
Tired of writing if statements every time you need to check if something's defined?
Make a little 'raise' function to throw an error, and inline it with a nullish coalescing operator.
Thanks to
@heyImMapleLeaf
for this one.
By far the strangest TypeScript trick I've ever come across is the Loose Autocomplete trick.
No idea who discovered this, but it's become widely used by OSS wizards.
It's now even used by React's types to type attributes like aria-role.
You probably know React.
But do you know how to use TypeScript with React?
Introducing my biggest ever drop of FREE content...
And it's live right now ⬇️⬇️⬇️
Someone DM'd me a question and we ended up drafting this awesome piece of code.
Turns out, yes, you can turn an 'as const' object into a crazy union of routes.
Array<T> vs T[] - which should you use in TypeScript?
I think the difference is close enough to be subjective - but here's everything I know:
The two syntaxes are functionally identical - you can use them interchangeably.
keyof T[] is a massive gotcha. Instead of it resulting…
JavaScript's new 'using' keyword is awesome for mocking in tests.
It automatically disposes the 'mock' when it leaves scope. 🤯
No more beforeEach/afterEach...
In State of JS 2022, 70% of respondents said they use TypeScript.
DHH is welcome to his opinions.
But to call the TS community a 'tribe' (instead of, say, a 'majority') feels, at this point, totally inaccurate.
"So farewell, TypeScript. May you bring much rigor and satisfaction to your tribe while letting the rest of us enjoy JavaScript in the glorious spirit it was originally designed: Free of strong typing."
Worried about fetch and JSON.parse returning any?
Drop these lines of code into any module and they'll return unknown across your entire project instead.
🔥 TypeScript Tip 🔥
Omit and Pick are the gateway to understanding type-level programming.
They let you start deriving types, instead of redeclaring them.
Need to manually type a JSON file?
I learned today you can add a .d.json.ts file to set your own type for a json import.
So, for data.json, it would be data.d.json.ts.
Inside, add:
Where Record<string, string> is the type you want to give the data.
Then, add this setting to…
I just KEEP seeing uses for Prettify<T> out in the wild.
Here, you can use it to unwrap a class with lots of complex inheritance to actually see it in the tooltip.
From next Monday, I'll be joining
@vercel
- as a developer advocate for
@turborepo
.
I can't wait to start contributing to a tool that I fell in love with at first sight.
I'm also so grateful they let me start part-time - meaning Total TypeScript is still full steam ahead.
🔥 TypeScript Tip 🔥
Creating a Context in React can be pretty annoying in TypeScript.
Here's my method for keeping things typesafe, minimizing use of 'as', and also ensuring folks use your custom hooks, instead of useContext.
TypeScript 5.4 will bring a new utility type: NoInfer.
This will be EXTREMELY useful for generic functions where you have multiple candidates for inferring a type.
In the example below, we use NoInfer to make sure that 'initial' must be one of the states passed.
My new VSCode extension is nearly ready. The goal is to teach you TypeScript without leaving your IDE. That means:
1⃣ Human-readable error translations (build on top of the TS error translator)
2⃣ Hoverable hints on TS syntax to explain what it means
I'm looking for testers.
'satisfies never' is SO GOOD for exhaustiveness checking in switch statements.
With this little annotation, you'll know you've checked every single branch of your union. Beautiful.
In two weeks’ time, I’ll be leaving Vercel to work on Total TypeScript full-time 🚀
Vercel is the most awesome company I’ve ever worked for, and I’m super proud of everything we shipped in my short time there.
But it’s time to go all-in on education. I’m so excited.
Here's a fun little TS snippet for grabbing all the keys starting with `on` from an object.
How does it work? Using '&' on keyof with a template literal means that only the ones that match _both_ are preserved.
🔥 TypeScript Tip 🔥
You can use 'as const' on a template literal to force TypeScript to infer it.
Without the as const, it defaults to string. With it, it goes DEEP.
You've been asking for it.
A single spot with ALL of my 2-minute TypeScript tips, in chronological order - with transcripts.
This might be the highest value-density of ANYTHING I've ever put out.
Enjoy, wizards 🧙
Say it with me:
TypeScript was built to make your IDE more powerful.
If you don't use TypeScript, your IDE will do a worse job of helping you.
It's as simple as that.
This morning I wrote a 9-exercise TypeScript course for beginners, and quietly made it public on GitHub.
This evening, someone's already been through the whole thing and is providing helpful feedback 🤯
I'm not worthy, y'all ❤️
Imagining a CLI that:
- You run on your tsconfig.json
- Asks you a BUNCH of questions about your setup and what you're building.
- Sets your tsconfig.json to the right values
- Tells you WHY it's adding those values and links you to the right resources.
Would you use it?
The '{}' type is a bit magic in TypeScript.
Instead of representing "any object", it actually represents "anything that isn't null or undefined".
This is probably the biggest WTF moment from my course.
The new 'using' keyword in TS 5.2 gets _really_ exciting when you combine it with 'await'.
So many use cases. Database connections, file handles - any long-running connection that needs to be closed automatically.
A lot of people talk about generic React components.
But I think the MUCH more useful tip (and often easier to grok) is using discriminated unions in React props.
Here, we make a version of the 'as' prop to choose between the 'button' and 'a' tags, with different props on both.
In every codebase where I need an API, I always end up writing some version of this function.
It lets you automatically handle 400 validation using Zod, and automatically infers the types based on the schema passed in.
Fun fact: you can export a value and a type with the SAME NAME.
This is great for when you have runtime things in your app that feel like types, like Zod schemas.
Are you using this technique? I'm a convert.
🔥 TypeScript Tip
#8
🔥
You can use generics in React to make incredibly dynamic, flexible components. Here, I make a Table component with a generic 'items' type.
Baby born 8pm on the 9th. Mum and baby well.
"Smiling, hardly able to restrain his tears, Levin kissed his wife and went out of the dark room. What he felt towards this little creature was utterly unlike what he had expected. There was nothing cheerful and joyous in the feeling;…
🪄 Announcing Advanced TypeScript🪄
Become a TypeScript Wizard with my upcoming video course.
💪 100+ type challenges
💡 Insights & Interviews with OS maintainers
🧙 Learn every TS trick in the book
🤩 Only intermediate knowledge needed
Sign up at
🔥 TypeScript Tip 🔥
This one's a little intense. Let's transform a discriminated union into a union.
Using this key remapping technique, we can properly iterate through each member of the union and transform it 🤯
Looks crazy, but ends up being a really nice mental model.
How should you type React Props?
You've got three options. type, interface or an inline object literal.
Inline object literals might be fast to write, but it means you can't extract the type out for use elsewhere in your codebase:
This makes them hard to recommend.
So,…
🔥 TypeScript Tip 🔥
Got a utility type like Maybe<T> that you just want to use everywhere without importing it?
Stick it in a declare global {}, and boom - it's global!
🔥 TypeScript Tip 🔥
Checking out TS codebases like
@excalidraw
's has been so enlightening - especially how many of them are using 'as const' over enums.
🔥 TypeScript Tip
#5
🔥
The 'extends' keyword is very powerful in TypeScript. Here, I use it to narrow the value of a generic to enable some beautiful autocomplete/inference.
You run tsc --init.
You get these options in your tsconfig.json.
What rules are you immediately changing/adding?
For me, first stop is:
"noUncheckedIndexedAccess": true
Gotta have type safety on my object/array access, y'all.
Next, sort out the module resolution:…
as const fixes everything.
Making a custom hook that returns a tuple?
You've probably hit this weird error before.
This is happening because TypeScript thinks your hook returns an array, not a tuple.
So, add an 'as const' to make it infer properly.
Is there anything 'as…
Starting a new series on YT: BLAZING FAST tips.
Basically, it's my usual format, but INCREDIBLY condensed and concise.
We'll be kicking off with React + TypeScript. Starts tomorrow. Get ready.
🎉 SO excited to announce what I've been working on for the past few months...
✨🧙♂️ Total TypeScript 🧙♂️✨
It's a comprehensive, interactive video course to turn you into a TypeScript wizard.
Prerelease available now! ⬇️⬇️⬇️
When you're creating some config in TS, you've got two choices for how you write the type.
Either DECLARE the type, then use it to type the value.
Or DERIVE the type from the value.
Which do you prefer?