TypeScript cheatsheet
TypeScript cheatsheet
Utility types, narrowing tricks, the syntax that gets forgotten between projects.
Utility types
Partial<T>every property optionalRequired<T>every property non-optionalReadonly<T>all properties readonlyPick<T, "a" | "b">subset of keysOmit<T, "a">subtract keysRecord<K, V>object with K keys, V valuesReturnType<typeof fn>the return type of fnAwaited<T>unwrap a Promise<T>NonNullable<T>remove null | undefinedNarrowing patterns
Discriminated unions
type Result =
| { ok: true; value: number }
| { ok: false; error: string };
function handle(r: Result) {
if (r.ok) return r.value; // narrowed to success
return r.error; // narrowed to failure
}Exhaustive switch via never
function area(s: Shape): number {
switch (s.kind) {
case 'square': return s.side ** 2;
case 'circle': return Math.PI * s.radius ** 2;
default: {
const _: never = s; // compile error if a case is missed
return _;
}
}
}Common gotchas
Index signatures (`{[k: string]: T}`) make ALL access return `T | undefined` when `noUncheckedIndexedAccess` is on. Treat that as a feature.
`as const` on object literals locks property types to their literal values — perfect for config tables.
Prefer `satisfies` over `as` when you want type-checking against a wider type but to keep the narrow inferred shape.