Primitive Types
let n: number = 42Number - integer or floatlet s: string = "hello"Stringlet b: boolean = trueBooleanlet u: undefined = undefinedUndefinedlet nu: null = nullNulllet sym: symbol = Symbol("key")Symbollet big: bigint = 9007199254740991nBigIntlet x: anyany - opt out of type checkinglet x: unknownunknown - like any but requires type check before usefunction fail(): never { throw new Error() }never - function that never returnsfunction log(): void { console.log() }void - function returns nothinglet x = 42Type inference - TypeScript infers numberArrays & Tuples
let arr: number[] = [1, 2, 3]Typed arraylet arr: Array<string> = ["a", "b"]Generic array syntaxlet pair: [string, number] = ["age", 30]Tuple - fixed length, typed positionslet tuple: [string, ...number[]] = ["n", 1, 2, 3]Rest element in tupleconst arr: readonly number[] = [1, 2]Read-only arrayconst arr: ReadonlyArray<number> = [1, 2]Generic read-only arrayInterfaces & Type Aliases
interface User { id: number; name: string; }Interface definitioninterface User { email?: string; }Optional propertyinterface User { readonly id: number; }Read-only propertyinterface User { [key: string]: unknown; }Index signature - dynamic propertiesinterface Admin extends User { role: string; }Interface extensioninterface A extends B, C { }Extend multiple interfacestype Point = { x: number; y: number; }Type alias - object shapetype ID = string | numberUnion type aliastype Named = { name: string } & { age: number }Intersection typetype Alias = stringSimple type aliasFunctions
function add(a: number, b: number): number { return a + b; }Typed functionconst add = (a: number, b: number): number => a + bArrow function with typesfunction greet(name?: string): stringOptional parameterfunction greet(name: string = "World"): stringDefault parameterfunction sum(...nums: number[]): numberRest parametertype AddFn = (a: number, b: number) => numberFunction type aliasinterface AddFn { (a: number, b: number): number }Function interfacefunction id<T>(x: T): T { return x; }Generic functionfunction first<T>(arr: T[]): T | undefinedGeneric with constraintfunction len<T extends { length: number }>(x: T): numberGeneric with constraintfunction parse(x: string): number; function parse(x: number): string;Function overloadsClasses
class User { name: string; constructor(name: string) { this.name = name; } }Basic classclass User { constructor(public name: string, private id: number) {} }Constructor shorthand - declares and assignsclass User { readonly id: number = Math.random(); }Readonly propertyclass User { #secret = "hidden"; }Private field (ES private - truly private)class User { private secret = "hidden"; }TypeScript private - compile-time onlyclass User { protected role = "user"; }Protected - accessible in subclassesclass Admin extends User { }Class inheritancesuper(args)Call parent constructorclass User implements IUser { }Implement interfaceabstract class Shape { abstract area(): number; }Abstract class and methodclass Box<T> { constructor(public value: T) {} }Generic classget name(): string { return this._name; }Getterset name(v: string) { this._name = v; }Setterstatic count = 0Static class propertyUnion, Intersection & Narrowing
type ID = string | numberUnion typetype Named = { name: string } & { age: number }Intersection type - merge all propertiesif (typeof x === "string") { }typeof narrowingif (x instanceof Date) { }instanceof narrowingif ("name" in obj) { }in narrowing - check property existenceif (x === null) { }Null check narrowingfunction isUser(x: any): x is User { return "name" in x; }Type predicate (user-defined type guard)function assertUser(x: any): asserts x is User { }Assertion functionx!Non-null assertion - tells TS x is not null/undefinedx as stringType assertion (cast)x as unknown as TDouble assertion - bypass incompatible castGenerics
function wrap<T>(val: T): { value: T }Generic functioninterface Box<T> { value: T }Generic interfacetype Pair<A, B> = { first: A; second: B }Generic type alias<T extends string | number>Constrain generic to specific types<T extends object>Constrain to object types<T, U extends T>U must extend Tfunction getProp<T, K extends keyof T>(obj: T, key: K): T[K]keyof constraint<T = string>Generic default typeUtility Types
Partial<User>All properties optionalRequired<User>All properties requiredReadonly<User>All properties read-onlyPick<User, "id" | "name">Keep only specified propertiesOmit<User, "password">Remove specified propertiesRecord<string, number>Object with specific key and value typesExclude<"a" | "b" | "c", "a">Remove types from union - result: "b" | "c"Extract<"a" | "b" | number, string>Keep types in union - result: "a" | "b"NonNullable<string | null | undefined>Remove null and undefined - result: stringReturnType<typeof fn>Infer return type of a functionParameters<typeof fn>Infer parameter types as tupleInstanceType<typeof MyClass>Infer instance type of a classAwaited<Promise<string>>Unwrap promise type - result: stringMapped & Conditional Types
type Opt<T> = { [K in keyof T]?: T[K] }Mapped type - make all optionaltype Ro<T> = { readonly [K in keyof T]: T[K] }Mapped type - make all read-onlytype Str<T> = { [K in keyof T]: string }Remap all values to stringtype GetStr<T> = T extends string ? T : neverConditional typeT extends U ? X : YConditional type syntaxtype Flat<T> = T extends Array<infer U> ? U : Tinfer - extract type within conditionaltype Keys<T> = keyof Tkeyof - union of property keystype Val<T, K extends keyof T> = T[K]Indexed access typetype E = 'a' | 'b'; type Obj = { [K in E]: K }Template mapped type over union`${string}Id`Template literal typeUppercase<S> / Lowercase<S> / Capitalize<S>Intrinsic string manipulation typesEnums & Literals
enum Direction { Up, Down, Left, Right }Numeric enum - values 0, 1, 2, 3enum Direction { Up = "UP", Down = "DOWN" }String enumconst enum Size { S = 1, M, L }Const enum - inlined at compile timetype Dir = "up" | "down" | "left"String literal union - preferred over enumtype Code = 200 | 404 | 500Numeric literal unionconst obj = { a: 1, b: 2 } as constas const - narrow to literal types, readonlytype Keys = keyof typeof objExtract keys of a const object as uniontype Vals = typeof obj[keyof typeof obj]Extract values of a const object as unionconst directions = ["north","south","east","west"] as constas const on array - creates readonly tuple of literalstype Direction = typeof directions[number]Union type from const array: 'north'|'south'|...Modules & Declarations
export type { User }Type-only export (erased at runtime)import type { User } from "./types"Type-only importdeclare const __DEV__: booleanAmbient declaration - no implementationdeclare module "*.svg" { const src: string; export default src; }Module augmentation for non-TS filesdeclare global { interface Window { myVar: string; } }Augment global types/// <reference types="node" />Triple-slash directive - include type definitions"strict": true in tsconfig.jsonEnable all strict checks - recommended"noUncheckedIndexedAccess": trueIndex signatures return T | undefinedAdvanced Type Patterns
type Vals = (typeof arr)[number]Get array element typetype StringKeys<T> = { [K in keyof T]: T[K] extends string ? K : never }[keyof T]Filter keys by value typetype Flatten<T> = T extends Array<infer U> ? U : TFlatten array type one leveltype DeepReadonly<T> = { readonly [K in keyof T]: DeepReadonly<T[K]> }Recursive mapped type patterntype RequiredFields<T, K extends keyof T> = T & Required<Pick<T, K>>Make specific fields requiredTemplate Literal Types
type EventName = `on${string}`Template literal typetype PropEvent<T extends string> = `${T}Changed`Parameterised template literaltype Getter<T extends string> = `get${Capitalize<T>}`With intrinsic string utilityUppercase<T>Intrinsic: uppercase string typeLowercase<T>Intrinsic: lowercase string typeCapitalize<T>Intrinsic: capitalize first charUncapitalize<T>Intrinsic: lowercase first chartype Endpoint = `${'GET'|'POST'} ${'/users'|'/posts'}`Combine unions in template literal (generates all combos)Discriminated Unions
type Shape = { kind: "circle"; r: number } | { kind: "rect"; w: number; h: number }Discriminated union with kind tagswitch (shape.kind) { case "circle": ... }Discriminant narrows the unionif (shape.kind === "circle") shape.rNarrows in if blocktype Result<T> = { ok: true; value: T } | { ok: false; error: string }Discriminated Result typefunction assertNever(x: never): never { throw new Error() }Exhaustiveness checksatisfies Operator
const palette = { red: [255,0,0] } satisfies Record<string, [number,number,number]>Validate type without widening (TypeScript 4.9+)palette.redInferred as [number,number,number], not generic arrayconst config = { port: 3000 } satisfies { port: number; host?: string }Keeps literal types while checking shape