Command Palette

Search for a command to run...

Hectal
Phase 10Advanced11 of 18 in TypeScript

Utility Types and Type-Level Patterns

The built-in utility types and how each is built, your own utilities, branded types, illegal states that cannot be written, and knowing when types get too clever.

TypeScript ships a toolbox of small helper types: Partial, Pick, Omit, Record, ReturnType, Awaited and more. They look like magic until you see that each is only a few lines of the mapped and conditional types you met in Phases 8 and 9. In this phase you'll read the real definition of every one, then build it yourself and check each step with // ^?.

Then you'll go past the built-ins: your own utilities such as DeepPartial and RequireAtLeastOne, branded types so a UserId can never be passed where an OrderId is expected, and designs where an impossible state simply cannot be written down.

The last topic is about judgement. Clever types can make code harder to read, slow the compiler and produce unreadable errors. You'll learn how to test your types, when to use @ts-expect-error, and when to stop.

0/6 · 0%
6 topics ~2 h 17 code blocks & diagrams
Start with the first topic
1
10.1

Object Utility Types

Partial, Required, Readonly, Pick, Omit and Record make a new object type from an old one. Each is a one-line mapped type, and writing them yourself shows exactly what they do.

21 min 2 code practice

2
10.2

Union and Function Utility Types

Exclude, Extract and NonNullable filter a union, while ReturnType, Parameters, InstanceType, Awaited and the this helpers pull types out of functions and classes. All are small conditional types using infer.

23 min 3 code practice

3
10.3

Building Your Own Utilities

When the built-ins aren't enough you write your own: DeepPartial, Mutable, PickByValue and RequireAtLeastOne. The method is the same every time: start tiny, ask // ^? after every step, and fix what the answer shows.

21 min 4 code practice

4
10.4

Branded and Nominal Types

TypeScript compares types by shape, so a UserId and an OrderId that are both numbers are interchangeable. A brand is a fake extra property that makes them different types, and a constructor function is the one door that hands out branded values.

20 min 2 code practice

5
10.5

Making Illegal States Unrepresentable

Instead of checking at runtime that a combination of values is allowed, shape the types so the wrong combination cannot even be written. Unions for states, typed builders, exhaustive Record maps and satisfies do most of the work.

22 min 3 code practice

6
10.6

When Types Get Too Clever

Type-level code can check a lot, but it can also be unreadable, slow the compiler, hit depth limits and produce error messages nobody understands. Learn to test your types, use @ts-expect-error correctly, and stop at the right moment.

22 min 3 code practice

Practise this phase

Hands-on exercises: write the code, see your page live, and press Check to have it tested automatically.