TypeScript adds static types to JavaScript: primitives, structured types, generics, and compile-time checks that erase at runtime when transpiled to JS.
How to use this TypeScript cheat sheet
Core syntax covers primitives, arrays, tuples, interfaces, type aliases, unions, and narrowing with typeof, in, and discriminated unions. Utility types like Partial, Pick, and Record reshape existing types without duplication.
Generics parameterize types and functions; satisfies validates shape without widening; as const freezes literals. Enable strict in tsconfig for null safety, implicit any errors, and reliable inference across your codebase.
Quick TypeScript example
interface User {
id: string;
name: string;
role: 'admin' | 'member';
}
type UserId = User['id'];
function getUser(id: UserId): Promise<User | undefined> {
return fetch('/api/users/' + id).then((r) => r.json());
}
const config = {
theme: 'dark',
retries: 3,
} as const satisfies { theme: 'dark' | 'light'; retries: number };
Primitives & Collections
Syntax
Example
Notes
Primitives
let n: number; let s: string; let ok: boolean;
number includes all JS numbers (no int/float split)
Arrays
string[] or Array<string>
Homogeneous arrays; readonly T[] for immutability
Tuples
[string, number]
Fixed-length arrays with typed positions
Literal types
type Dir = "up" | "down"
Restrict to specific string/number values
any vs unknown
unknown requires narrowing before use
Prefer unknown over any for external data
void & never
(): void vs (): never
void returns undefined; never means no return (throws)
Optional props
email?: string
Equivalent to email: string | undefined
Readonly
readonly string[]
Prevents mutating methods on arrays and tuples
Interfaces vs Type Aliases
Feature
Example
Notes
Interface
interface Point { x: number; y: number; }
Extendable; good for object shapes and classes
Type alias
type Point = { x: number; y: number; }
Can represent unions, tuples, mapped types
Extends
interface A extends B, C {}
Multiple interface inheritance
Intersection
type AB = A & B
Merge types; conflicts become never
Declaration merge
interface Window { myApp: App; }
Interfaces merge; type aliases do not
Implement
class C implements I {}
Classes implement interfaces, not type aliases with unions
Index signature
[key: string]: number
Dynamic keys on objects
Call signature
type Fn = (x: number) => string
Describe function types in type aliases
Narrowing & Generics
Pattern
Example
Notes
typeof
if (typeof x === "string")
Narrows primitives
in operator
if ("swim" in pet)
Narrows union by property presence
Discriminant
if (action.type === "ADD")
Tagged unions with shared literal field
Generic fn
function id<T>(x: T): T
Preserve input type through function
Constraint
<T extends { id: string }>
Limit generic to shapes with id
Generic interface
interface Box<T> { value: T; }
Reusable typed containers
Default type param
<T = string>
Fallback when type argument omitted
infer keyword
type R = T extends (...args: infer A) => infer R ? R : never
Extract types inside conditional types
Utility Types & Strict Config
Utility
Example
Purpose
Partial
Partial<User>
All properties optional
Required
Required<User>
All properties required
Pick
Pick<User, "id" | "name">
Subset of properties
Omit
Omit<User, "password">
Exclude properties
Record
Record<string, number>
Object with keyed index type
ReturnType
ReturnType<typeof fn>
Extract function return type
satisfies
const c = { a: 1 } satisfies Config
Validate without widening inferred literals
strict flags
"strict": true in tsconfig
Enables strictNullChecks, noImplicitAny, and related checks
Discriminated union narrowing
type Result =
| { ok: true; data: string }
| { ok: false; error: string };
function handle(r: Result) {
if (r.ok) return r.data.toUpperCase();
throw new Error(r.error);
}
Shared literal field (ok) enables exhaustive narrowing in if/switch.