Utility Types
Partial<T> // all props optional
Required<T> // all props required
Readonly<T> // all props readonly
Pick<T, K> // keep only keys K
Omit<T, K> // remove keys K
Record<K, V> // object type with keys K and values V
Exclude<T, U> // T minus types assignable to U
Extract<T, U> // T intersected with U
NonNullable<T> // remove null | undefined
ReturnType<F> // return type of function F
Parameters<F> // parameter tuple of function F
Awaited<T> // unwrap Promise<T>
Generics
function identity<T>(arg: T): T { return arg }
// Constrained generic
function getKey<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key]
}
// Default type parameter
type ApiResponse<T = unknown> = { data: T; status: number }
Narrowing
// Type guard function
function isString(val: unknown): val is string {
return typeof val === "string"
}
// Discriminated union
type Result<T> =
| { ok: true; data: T }
| { ok: false; error: string }
function handle(r: Result<number>) {
if (r.ok) console.log(r.data) // narrowed to { ok: true; data: number }
else console.log(r.error)
}
Mapped Types
type Optional<T> = { [K in keyof T]?: T[K] }
type Nullable<T> = { [K in keyof T]: T[K] | null }
type Getters<T> = { [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K] }
Template Literal Types
type EventName<T extends string> = `on${Capitalize<T>}`
type ClickEvent = EventName<"click"> // "onClick"
Conditional Types
type IsArray<T> = T extends any[] ? true : false
type Flatten<T> = T extends Array<infer U> ? U : T
satisfies operator
const config = {
port: 3000,
host: "localhost",
} satisfies Record<string, string | number>
// infers literal types while validating shape
Common tsconfig.json options
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"verbatimModuleSyntax": true,
"paths": {
"@/*": ["./src/*"]
}
}
}