Every TypeScript type construct you actually reach for in production, in one place. Utility types, conditional types, mapped types, generics, type guards, and the patterns that tie them together. No fluff, no toy examples. Bookmark it.
| Name | Syntax | Description |
|---|---|---|
| Partial<T> | Partial<User> | Makes all properties optional. Use for PATCH/update payloads. |
| Required<T> | Required<Config> | Makes all properties required. Strips every ? modifier. |
| Pick<T, K> | Pick<User, "id" | "name"> | Keeps only the listed properties. Good for API response shaping. |
| Omit<T, K> | Omit<User, "password"> | Drops the listed properties. Inverse of Pick. |
| Record<K, V> | Record<string, unknown> | Object type with keys K and values V. Great for lookup tables. |
| Readonly<T> | Readonly<State> | Makes all properties readonly. Shallow only, does not freeze nested objects. |
| ReturnType<T> | ReturnType<typeof fn> | Extracts the return type of a function. Pair with typeof for values. |
| Parameters<T> | Parameters<typeof fn> | Extracts parameter types as a tuple. Index with [0], [1] for individual params. |
| Awaited<T> | Awaited<Promise<Response>> | Recursively unwraps Promise types. Handles nested Promise<Promise<T>>. |
| Extract<T, U> | Extract<Event, { type: "click" }> | Keeps union members assignable to U. Filters discriminated unions. |
| Exclude<T, U> | Exclude<Status, "error"> | Removes union members assignable to U. Returns the rest. |
| NonNullable<T> | NonNullable<string | null> | Strips null and undefined from a union. Shorthand for Exclude<T, null | undefined>. |
| keyof T | keyof User | Union of all property keys: "id" | "name" | "email". Foundation of type-safe access. |
| typeof value | typeof config | Captures the type of a runtime value. Combine with as const for literal types. |
| infer | T extends Promise<infer R> ? R : T | Declares a type variable inside an extends clause. The compiler fills it in. |
Partial<T> | Required<T> | Readonly<T>Partial makes every property optional (for updates), Required strips all ? modifiers (for resolved configs), and Readonly prevents property reassignment. All three are mapped types under the hood: { [P in keyof T]?: T[P] }.
Tips
Pick<T, K> | Omit<T, K> | Record<K, V>Pick selects properties by name, Omit removes them, and Record builds a dictionary from a key union and value type. Use Pick when listing inclusions is clearer; use Omit when exclusions are fewer.
Tips
Extract<T, U> | Exclude<T, U> | NonNullable<T>These operate on union members, not object properties. Exclude removes members assignable to U, Extract keeps them, and NonNullable is just Exclude<T, null | undefined>. They rely on distributive conditional types.
Tips
ReturnType<T> | Parameters<T> | Awaited<T>ReturnType extracts what a function returns, Parameters extracts its argument tuple, and Awaited recursively unwraps Promise types. Always pair these with typeof when working with function values (not types).
Tips
T extends U ? X : YConditional types bring if/else logic to the type system. The extends keyword checks assignability: if T is assignable to U, resolve to X, otherwise Y. This is how Exclude, Extract, ReturnType, and most utility types are built.
Tips
T extends (...args: infer P) => infer R ? [P, R] : neverinfer declares a type variable inside an extends clause that TypeScript fills in from context. It can capture return types, parameter types, promise contents, tuple elements, and template literal parts. Only valid inside the condition of a conditional type.
Tips
{ [K in keyof T]: NewType }Mapped types iterate over keys with [K in keyof T] and produce a new type for each property. Modifiers +/- control readonly and ?. Key remapping with as lets you rename or filter keys during the mapping.
Tips
{ [K in keyof T as NewKey]: T[K] }The as clause in mapped types transforms or filters keys. Return never to drop a key. Use conditional types in the value position to selectively transform property types (like converting Date to string for JSON).
Tips
`prefix-${Union}`Template literal types use backtick syntax to construct string types at compile time. When a union is interpolated, TypeScript generates every possible combination (cross product). Use Capitalize, Uppercase, Lowercase, and Uncapitalize for casing transforms.
Tips
Uppercase<S> | Lowercase<S> | Capitalize<S> | Uncapitalize<S>Four compiler-intrinsic types for string case manipulation. They distribute over unions and work inside template literal positions. Capitalize and Uncapitalize touch only the first character; Uppercase and Lowercase transform all characters.
Tips
typeof x === "string" | x instanceof Errortypeof checks narrow to primitive types (string, number, boolean, symbol, bigint, undefined, object, function). instanceof checks narrow to class instances. TypeScript narrows the type in the truthy branch automatically.
Tips
function isX(value: unknown): value is XA type predicate (value is Type) tells TypeScript to narrow the parameter's type in the calling scope when the function returns true. Use for runtime validation of unknown data (API responses, parsed JSON, external inputs).
Tips
<T extends Constraint>Generics with constraints (extends) restrict what types can be passed. The classic pattern is <T, K extends keyof T> for type-safe property access. Generic defaults (= unknown) provide a fallback when the type is not specified.
Tips
typeof + as const + keyofDefine constants once with as const, then derive all types with typeof, keyof, and indexed access. This eliminates type/value duplication. Changes to the runtime object automatically update all derived types.
Tips
A discriminated union with success as the discriminant. TypeScript narrows the type in each branch, giving you data in the success branch and error in the failure branch. This pattern eliminates entire classes of null-check bugs in API code.
Derive all form-related types from a single schema interface. FormErrors and FormTouched use Record<keyof T, ...> to mirror the field names. This guarantees that adding a field to the schema updates validation, touched tracking, and form state automatically.
A generic event emitter where the event map type constrains both event names and payload shapes. Each handler receives the exact payload type for its event. Adding a new event to EventMap automatically makes it available with full type checking.
Readonly<T> is shallow. You freeze the top-level properties but nested objects and arrays are still mutable.
Build a DeepReadonly type: type DeepReadonly<T> = { readonly [K in keyof T]: T[K] extends object ? T[K] extends Function ? T[K] : DeepReadonly<T[K]> : T[K] }. Or use Object.freeze at runtime, which has the same shallow limitation in JS. For production immutability, consider Immer.
Distributive conditional types catch people off guard. Exclude<string | number, string> returns number, but Exclude<never, string> returns never (not the identity). never distributes to zero iterations.
Wrap in a tuple to prevent distribution when you need to check the union as a whole: [T] extends [U] ? X : Y. Use the wrapped form for IsNever<T>: [T] extends [never] ? true : false. Without the wrapper, the condition is never entered because never has zero members.
Omit<T, K> does not error when K includes keys that do not exist on T. Omit<User, 'nonexistent'> compiles silently and does nothing.
If you want strict Omit that catches typos, define your own: type StrictOmit<T, K extends keyof T> = Omit<T, K>. The extends keyof T constraint ensures K is a valid key. The built-in Omit uses K extends string | number | symbol, which is intentionally loose.
Using as const on an object literal makes every property readonly and literal-typed, but assigning it to a wider type first loses the literal types. const x: Record<string, string> = { a: 'b' } as const wipes out the literal.
Declare the variable without a type annotation and let inference do its job: const x = { a: 'b' } as const. If you need validation against a shape, use satisfies instead of a type annotation: const x = { a: 'b' } as const satisfies Record<string, string>. This preserves literal types while checking the structure.
Type predicates (is) lie to the compiler if the runtime check is wrong. function isString(x: unknown): x is string { return true } narrows to string even when x is a number.
Treat type predicates as a contract. The runtime check must exactly match what the return type claims. Test your type guards with edge cases. Consider using Zod's .safeParse() or io-ts for schema validation instead of hand-written predicates for complex shapes.
Go beyond the cheatsheet with hands-on lessons and challenges.