TypeScript Advanced Types
Utility, Mapped & Conditional Types
TypeScript's type system is Turing-complete. Utility types, mapped types, and conditional types let you compute new types from existing ones, keeping a single source of truth.
TypeScript 5
3 Topics
01
Built-in Utility Types
TypeScript ships type transformers that derive new types from a base type — so you define a shape once and reuse variations of it.
| Utility | Turns | Into |
|---|---|---|
Partial<T> | All props required | All props optional |
Required<T> | Optional props | All required |
Readonly<T> | Mutable props | All readonly |
Pick<T, K> | Full type | Just keys K |
Omit<T, K> | Full type | Type without keys K |
Record<K, V> | Key set K, value V | Object type |
ReturnType<F> | Function type | Its return type |
TypeScript — Utility Types
interface User { id: string; name: string; email: string; } // a "patch" where every field is optional type UserUpdate = Partial<User>; // { id?; name?; email? } // a public shape without the email type PublicUser = Omit<User, "email">; // { id; name } // just the fields you need type Credentials = Pick<User, "email">; // { email } // a lookup map type UsersById = Record<string, User>; // { [id: string]: User }
Deriving types with these utilities keeps a single source of truth. Change
User and every derived type (Partial, Omit, ...) updates automatically. No duplicated interfaces to keep in sync.02
Mapped Types
A mapped type transforms every property of a type by iterating over its keys. This is exactly how the utility types above are built.
TypeScript — Mapped Types
// make every property optional (this IS how Partial works) type MyPartial<T> = { [K in keyof T]?: T[K]; }; // make every property nullable type Nullable<T> = { [K in keyof T]: T[K] | null; }; // modifiers: - removes, + adds. Here we strip readonly and optional type Mutable<T> = { -readonly [K in keyof T]-?: T[K]; };
03
Conditional Types & infer
A conditional type (T extends U ? X : Y) picks one of two types based on a condition. The infer keyword captures a type from within another type — how ReturnType extracts a function's return.
TypeScript — Conditional & infer
// conditional type — choose based on the type type IsString<T> = T extends string ? true : false; type A = IsString<"hi">; // true type B = IsString<42>; // false // infer — extract a type from a bigger one type ElementOf<T> = T extends (infer E)[] ? E : never; type C = ElementOf<number[]>; // number // how ReturnType is defined type MyReturnType<F> = F extends (...args: any[]) => infer R ? R : never; type R = MyReturnType<() => string>; // string
Conditional and mapped types are powerful but can become hard to read fast. Use them for genuine reuse (library types, framework glue). For everyday app code, plain interfaces and unions are usually clearer.
✓
Quick Quiz
1. Partial<User> makes every property…
2. To drop a property from a type, use…
3. [K in keyof T] is the syntax of a…
4. T extends U ? X : Y is a…
5. The infer keyword is used to…