Matt Pocock Profile picture
Full-time TS/AI educator. Ex-@vercel, @statelyai. Used to be a voice coach. He/him. Author of Total TypeScript 🧙 Hire me to teach your team TypeScript!
5 subscribers
Oct 1 7 tweets 2 min read
z.strict() fixed a nasty bug for me this morning.

You should probably be using it on most of the schemas that handle outside data.

Here's the bug 🧵 Image I had a form where I was marking the date a post was posted. I was expecting a key of `postedAt`, with an optional datetime. Image
Aug 20 13 tweets 3 min read
Narrowing down the types of values is key knowledge for any TypeScript dev.

Here's 11 different ways you can do it. I bet you won't know 2 or 3 of them!

🧵 Narrowing with typeof: Image
Aug 8 10 tweets 3 min read
So many folks don't know about structuredClone.

It's awesome, built-in, and supported in all major browsers.

Let's learn 🧵 Image A common pattern in JavaScript is to create an immutable clone of an object. This is useful when you want to make mutations to it without changing the original.

For that, you'll often see code using the spread operator: `{ ...obj }`. Image
Aug 7 4 tweets 1 min read
I'm starting to think that library types in TypeScript are all wrong.

Instead of top-level types, they should be available right on the functions that use them.

Brief thread 🧵 Image How is this possible? Well, it's due to a trick in the way namespaces work in TypeScript.

When you export a namespace with the same name as a function, TypeScript combines the two: Image
Aug 5 11 tweets 4 min read
I've changed my mind on .d.ts files.

If you're writing application code, you should NEVER use them.

Let me explain 🧵 Declaration files are files that only contain types.

They've got two purposes - providing types for JavaScript files, and augmenting types in the global scope.

Here's the section on them in my book:

buff.ly/3SDoL6p
Aug 5 7 tweets 3 min read
Sometimes, TypeScript's narrowing kind of sucks.

The prime suspect? Boolean.

Let's take a look at why. 🧵 Image Let's explain the code above. `myFunc` takes in a string or null. We want to ensure it's not null for some reason.

So, we can use an if statement to check if it's truthy. If it's truthy, it ain't null.

We can do that in MANY different ways: Image
Jul 9 12 tweets 4 min read
In celebration of my free book coming out, here's a massive thread of all my best free TypeScript resources.

I guarantee that if you work through this list, you'll be the top TypeScript wizard at your company.

🧵 We've got to start with the book. It's 16 chapters of totally free written content.

It goes from first principles all the way up to the bottom end of advanced.

It's the no-brainer place to start.

totaltypescript.com/books/total-ty…
Oct 24, 2023 6 tweets 3 min read
After all the chat about typing event handlers in React, I figured I'd write down all the suggestions folks gave.

Quick 🧵 Image The most popular solution is to hover the onChange attribute in the JSX, then use that to type your handler.

But this creates an astonishingly long type - very intimidating for newbies.
Image
Image
Sep 4, 2023 4 tweets 2 min read
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, interface vs type again. As I've said before, I prefer type.

But let's say you're building an input that needs to take all the props of 'input', but with an extra label.

For those cases, you must use interfaces:
Using an intersection here will slow down TypeScript on the scale of a large codebase. interface extends is the way to go.

This means that it's a good idea to get into the habit of using interfaces for each prop declaration.

I recommend using a code snippet to declare the interface for you:
All the speed of an object literal, but all the reusability and TS performance of an interface.

Want to share outside of X? Head to Total TypeScript:

totaltypescript.com/react-props-ty…
Jul 20, 2023 18 tweets 5 min read
If you don't understand generics in TypeScript, I think there's something you've misunderstood.

There is no such thing as a 'generic'.

🧵 Image There are generic types, generic functions, and generic classes.

There are type arguments, and type parameters.

You cannot 'pass' a generic, 'declare' it, or 'infer' it.

In other words, 'generic' is not a noun, it's an adjective.

totaltypescript.com/no-such-thing-…
Mar 7, 2023 5 tweets 1 min read
Lazy Dev Twitter:

Anyone know if it's possible to detect a QR code (or even just a fiducial) from a video using ffmpeg? I'm asking for a slightly hilarious reason.

I use ffmpeg for automatically editing my videos. When I screw up a take, I want to be able to hold up a QR code on a paddle to tell my editing software to discard that take.
Mar 6, 2023 20 tweets 7 min read
Why any's happen, how to stop them, and why unknown isn't necessarily a better solution 🧵

Any 'any' in a codebase is a cause for concern. That's because it disables typechecking on the thing it's assigned to.

Pass it to a function parameter? You then can't guarantee anything about that function parameter. const groupBy = (arr: any[], key: any) => {   const result:
Mar 3, 2023 5 tweets 2 min read
Working with mocks in TS sucks.

The only way you can make it work is by slapping 'as' on everything - which can make the tests hard to maintain.

What if you had a simple set of functions that could let you pass whatever you wanted, but with perfect autocomplete? import { partial, any } from "@total-typescript/mock-ut This feels pretty simple on the surface - many of you might have tried to make these kinds of abstractions before.

But it's harder than you think - you need a bit of wizardry. Let's take partial().

Why isn't the code below working? const partial = <T>(mock: Partial<T>): T => {   return mock
Mar 2, 2023 18 tweets 6 min read
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. const obj = {} satisfies Record<string, string>;  // Propert satisfies has added yet another tool to the TypeScript user's toolkit.

There are now _three_ ways to assign types to values.

Mar 1, 2023 10 tweets 2 min read
Today's the day.

Total TypeScript is ready. Your Total TypeScript adventure starts now 🧙 Hundreds of videos over three modules
🔥 The deepest exploration of Generics on the market
❤️ Interactive editors, transcripts, and thousands of words of accompanying articles
🪄 Perfect if you've used TS for a while, but want to achieve mastery

totaltypescript.com
Feb 20, 2023 12 tweets 5 min read
TypeScript annoys me sometimes.

So, I decided to do something about it... const arr = [1, 2, 3, undefined];  const result = arr.filter It's always bugged me that JSON.parse returns 'any'.

It means that, just by using an extremely common JS method, you're introducing a dangerous type into your codebase. // REAL LIFE  const result = JSON.parse("{}");  co
Feb 19, 2023 4 tweets 1 min read
👀 import "@total-typescript/ts-reset/fetch";  const 👀👀 import "@total-typescript/ts-reset/json-parse";  c
Feb 17, 2023 8 tweets 2 min read
An extremely incomplete TypeScript features type-safety tier list.

🧵 F-tier

as any
as unknown as X
// @ts-ignore
// @ts-expect-error

In application code, these should be avoided at all costs. You pretty much always have a better option.
Feb 17, 2023 9 tweets 4 min read
Just made three pull requests to @calcom to improve their types in small, subtle ways.

Take a look! You might learn something. github.com/calcom/cal.com…

Here, there were some globals being stored for safekeeping in the global scope.

I added their types using a declare global, meaning they could be safely accessed (and spotted a subtle bug in the process). ImageImage
Feb 15, 2023 24 tweets 7 min read
If you don't know generics, I promise you'll understand them by the end of this thread.

I like a challenge. export const objKeys = <T extends object>(obj: T) => {   ret What you might think of as generics in TypeScript is actually three separate concepts:

- Passing types to types
- Passing types to functions
- Inferring types from arguments passed to functions // 1. Passing types to types type PartialUser = Partial<{ id
Feb 13, 2023 13 tweets 4 min read
Let's talk about branded types.

If I were building an app where security was critical, I'd use the crap out of them. type User = {   id: string;... A Brand type lets you use a bit of 'nominal' typing inside TypeScript.

By declaring a unique symbol, 'brand', we can use this Brand type helper to create types with 'names'. declare const brand: unique...