TypeScript cheatsheet
Practical TypeScript 6 syntax for inference, narrowing, type transformations, declarations, and project checks.
TypeScript 6 1 page when printed
Declarations and inference
const port: number = 8080 give a binding an explicit value type let result: string | undefined declare a value that may be undefined const tags = ["ts", "types"] infer a mutable string array const role = "admin" as const retain the exact string literal type const pair = ["id", 42] as const infer a readonly literal tuple const config = { mode: "prod" } satisfies AppConfig check the shape without replacing the inferred type Objects and collections
type User = { readonly id: string; name?: string } describe readonly and optional object properties interface User { id: string; name?: string } declare an object contract that can be extended type Pair = [label: string, value: number] label tuple positions for readable tooling type Names = readonly string[] reject writes through an array type type Dictionary = { [key: string]: number } describe unknown keys with one value type type Entity = Identified & Timestamped combine two structural types declare const UserIdBrand: unique symbol; type UserId = string & { readonly [UserIdBrand]: true } create a nominal string type with a unique brand Function signatures
function parse(text: string): number { return Number(text); } annotate parameter and return types const handler: (event: Event) => void = (event) => event.preventDefault() contextually type a callback parameter type Formatter = (value: number, unit?: string) => string mark one callback parameter optional type Sum = (...values: number[]) => number type a rest parameter interface Parse { (value: string): number; (value: number): string } describe overloaded call signatures function handle(this: HTMLElement, event: Event): void {} declare the required call receiver Unions and narrowing
type Status = "idle" | "loading" | "done" restrict a value to listed literals type Result = { ok: true; value: string } | { ok: false; error: Error } build a discriminated result union typeof value === "string" narrow a primitive at runtime "role" in account narrow by property presence value instanceof Date narrow by a runtime constructor const isString = (value: unknown): value is string => typeof value === "string" define a reusable type predicate function assertString(value: unknown): asserts value is string { if (typeof value !== "string") throw new TypeError("Expected string"); } narrow after a validating assertion returns Generic constraints
function identity<T>(value: T): T { return value; } preserve the caller’s input type function first<T>(items: readonly T[]): T | undefined { return items[0]; } reflect that a collection may be empty function get<T, K extends keyof T>(value: T, key: K): T[K] { return value[key]; } accept only keys present on the object interface Box<T> { value: T } parameterize a reusable object contract type ApiResult<T, E = Error> = { data: T } | { error: E } give a type parameter a default class Store<T extends object> { constructor(readonly value: T) {} } constrain a class parameter to object types Type queries
type Config = typeof config derive a type from a value declaration type ConfigKey = keyof Config collect an object’s property keys as a union type Mode = Config["mode"] look up one property type type Item = (typeof items)[number] extract an array’s element type type ValueOf<T> = T[keyof T] collect an object’s property value types type Created = ReturnType<typeof createUser> extract a function’s return type type CreateArgs = Parameters<typeof createUser> extract parameters as a tuple Mapped transformations
type Optional<T> = { [K in keyof T]?: T[K] } make every property optional type Mutable<T> = { -readonly [K in keyof T]: T[K] } remove readonly property modifiers type Concrete<T> = { [K in keyof T]-?: T[K] } remove optional property modifiers type Flags<T> = { [K in keyof T]: boolean } map every property to one value type type Getters<T> = { [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K] } remap property names into getter names type StringsOnly<T> = { [K in keyof T as T[K] extends string ? K : never]: T[K] } keep only string-valued properties Conditional types and infer
type MessageOf<T> = T extends { message: unknown } ? T["message"] : never select a type when a property exists type Element<T> = T extends readonly (infer U)[] ? U : never infer a readonly array’s element type type Head<T> = T extends readonly [infer H, ...unknown[]] ? H : never infer the first element of a tuple type Unwrap<T> = T extends PromiseLike<infer U> ? Unwrap<U> : T recursively unwrap promise-like values type Distributed<T> = T extends unknown ? T[] : never distribute over each union member type NonDistributed<T> = [T] extends [unknown] ? T[] : never wrap the check to prevent distribution Literal composition
type Direction = "up" | "down" compose a finite string-literal union type Route = `/users/${string}` require a fixed route prefix type CssSize = `${number}px` require a numeric CSS pixel value type EventName<K extends string> = `on${Capitalize<K>}` derive a capitalized event name type EnvKey<K extends string> = `APP_${Uppercase<K>}` derive an uppercase environment key type Position = `${"top" | "bottom"}-${"left" | "right"}` generate every union combination Utility types
Partial<User> make every property optional Required<User> make every property required Readonly<User> make every property readonly Pick<User, "id" | "name" keep selected object properties Omit<User, "password" remove selected object properties Record<Status, Handler> map every key to one value type Exclude<Status, "error" remove members from a union Modules and declarations
import { value } from "./mod.js" import a runtime binding import type { User } from "./user.js" import a type without a runtime dependency export { value } from "./mod.js" re-export a runtime binding export type { User } from "./user.js" re-export a type without runtime code import data from "./data.json" with { type: "json" } use the current import-attribute syntax declare module "legacy-lib" { export function load(): unknown; } describe an untyped external module in a declaration file export {}; declare global { interface Window { appVersion: string } } augment the global scope from a module Compiler and projects
"strict": true keep strict checking explicit in shared configs "target": "es2025" select the TypeScript 6 ES2025 baseline "module": "nodenext" follow current Node module rules "types": ["node"] opt into Node ambient types under the empty default "rootDir": "./src" preserve the intended output tree explicitly npx tsc --noEmit check the configured project without emitting files npx tsc -b build a project-reference graph Say it precisely to your AI
rules pack · TypeScript
TypeScript rules for your coding agent
Download the track's pitfalls and review checks in the format your coding agent reads.