📋 Cheat Sheets

TypeScript Cheat Sheet — Types, Interfaces, and Generics


Click any item to expand the explanation and examples.

📦 Basic Types

Primitive Types basics
The fundamental types in TypeScript.
let name: string = "Alice";
let age: number = 30;
let active: boolean = true;
let data: null = null;
let value: undefined = undefined;
let id: bigint = 100n;
let key: symbol = Symbol("key");
Arrays & Tuples basics
Typed arrays and fixed-length tuples.
let nums: number[] = [1, 2, 3];
let names: Array<string> = ["Alice", "Bob"];

// Tuple: fixed length and types let pair: [string, number] = [“age”, 30]; let rgb: [number, number, number] = [255, 128, 0];

// Readonly tuple let point: readonly [number, number] = [10, 20];

any / unknown / never / void basics
Special types for edge cases.
let x: any = "anything";       // opt out of type checking
let y: unknown = "safe any";   // must narrow before use

function log(msg: string): void { // no return value console.log(msg); }

function fail(msg: string): never { // never returns throw new Error(msg); }

Prefer unknown over any — it forces you to check the type before using it.

🏗️ Interfaces & Type Aliases

interface types
Define object shapes. Can be extended and merged.
interface User {
  id: number;
  name: string;
  email: string;
  age?: number;              // optional
  readonly createdAt: Date;  // can't reassign
}

// Extend interface Admin extends User { role: “admin” | “superadmin”; }

// Method signatures interface API { getUser(id: number): Promise<User>; deleteUser(id: number): Promise<void>; }

type alias types
Name any type. More flexible than interfaces.
type ID = string | number;
type Status = "active" | "inactive" | "pending";
type Point = { x: number; y: number };
type Callback = (data: string) => void;

// Intersection (combine types) type Admin = User & { role: string };

Use interface for object shapes, type for unions, intersections, and primitives.

🔀 Union & Intersection Types

Union Types (A | B) unions
A value can be one of several types.
type ID = string | number;

function printId(id: ID) { if (typeof id === “string”) { console.log(id.toUpperCase()); // narrowed to string } else { console.log(id.toFixed(2)); // narrowed to number } }

// Literal unions type Direction = “up” | “down” | “left” | “right”; type HttpStatus = 200 | 301 | 404 | 500;

Intersection Types (A & B) unions
Combine multiple types into one.
type HasName = { name: string };
type HasAge = { age: number };
type Person = HasName & HasAge;

const p: Person = { name: “Alice”, age: 30 };

Discriminated Unions unions
Use a common property to narrow union types.
type Circle = { kind: "circle"; radius: number };
type Square = { kind: "square"; side: number };
type Shape = Circle | Square;

function area(shape: Shape): number { switch (shape.kind) { case “circle”: return Math.PI * shape.radius ** 2; case “square”: return shape.side ** 2; } }

🧬 Generics

Generic Functions generics
Write functions that work with any type.
function identity<T>(value: T): T {
  return value;
}

identity<string>(“hello”); // explicit identity(42); // inferred as number

function first<T>(arr: T[]): T | undefined { return arr[0]; }

Generic Constraints generics
Restrict what types a generic can accept.
function getLength<T extends { length: number }>(item: T): number {
  return item.length;
}

getLength(“hello”); // 5 getLength([1, 2, 3]); // 3 // getLength(42); // Error: number has no .length

// keyof constraint function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; }

Generic Interfaces & Types generics
Create reusable generic structures.
interface ApiResponse<T> {
  data: T;
  status: number;
  message: string;
}

type Result<T, E = Error> = | { ok: true; value: T } | { ok: false; error: E };

const res: ApiResponse<User[]> = { data: [{ id: 1, name: “Alice”, email: “a@b.c”, createdAt: new Date() }], status: 200, message: “OK” };

🛠️ Utility Types

Partial<T> / Required<T> utility
Make all properties optional or required.
interface User {
  name: string;
  email: string;
  age: number;
}

type UpdateUser = Partial<User>; // { name?: string; email?: string; age?: number }

type StrictUser = Required<User>; // all properties required, even if originally optional

Pick<T, K> / Omit<T, K> utility
Select or exclude specific properties.
type UserPreview = Pick<User, "name" | "email">;
// { name: string; email: string }

type UserWithoutAge = Omit<User, “age”>; // { name: string; email: string }

Record<K, V> utility
Create an object type with specific key and value types.
type Roles = "admin" | "user" | "guest";
type Permissions = Record<Roles, boolean>;
// { admin: boolean; user: boolean; guest: boolean }

const cache: Record<string, number> = {}; cache[“hits”] = 42;

Readonly<T> utility
Make all properties readonly.
type FrozenUser = Readonly<User>;

const user: FrozenUser = { name: “Alice”, email: “a@b.c”, age: 30 }; // user.name = “Bob”; // Error: readonly

// Also works with arrays const nums: ReadonlyArray<number> = [1, 2, 3]; // nums.push(4); // Error

Exclude / Extract / NonNullable utility
Filter union types.
type T = "a" | "b" | "c";

type WithoutA = Exclude<T, “a”>; // “b” | “c” type OnlyAB = Extract<T, “a” | “b”>; // “a” | “b”

type Maybe = string | null | undefined; type Sure = NonNullable<Maybe>; // string

ReturnType / Parameters utility
Extract types from functions.
function createUser(name: string, age: number) {
  return { name, age, id: Math.random() };
}

type NewUser = ReturnType<typeof createUser>; // { name: string; age: number; id: number }

type Args = Parameters<typeof createUser>; // [name: string, age: number]

🔒 Enums

Enums enums
Named constants. Prefer const enum or literal unions for most cases.
enum Direction {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT",
}

const move = Direction.Up; // “UP”

// Numeric enum (auto-increments) enum Status { Active, // 0 Inactive, // 1 Pending, // 2 }

// Prefer literal unions in most cases: type Direction = “UP” | “DOWN” | “LEFT” | “RIGHT”;

🛡️ Type Guards & Assertions

Type Guards guards
Narrow types at runtime.
// typeof
if (typeof value === "string") { /* string here */ }

// instanceof if (error instanceof TypeError) { /* TypeError here */ }

// in operator if (“email” in user) { /* has email property */ }

// Custom type guard function isUser(obj: unknown): obj is User { return typeof obj === “object” && obj !== null && “name” in obj; }

if (isUser(data)) { console.log(data.name); // safely narrowed }

Type Assertions guards
Tell TypeScript you know the type (use sparingly).
const input = document.getElementById("name") as HTMLInputElement;
input.value = "Alice";

// Alternative syntax const el = <HTMLInputElement>document.getElementById(“name”);

// Non-null assertion (!) const el = document.getElementById(“name”)!; // assert not null

Assertions don’t do runtime checks — they just tell the compiler to trust you.

🧪 Advanced Types

Mapped Types advanced
Transform properties of an existing type.
// Make all properties optional (this is how Partial works)
type MyPartial<T> = {
  [K in keyof T]?: T[K];
};

// Make all properties nullable type Nullable<T> = { [K in keyof T]: T[K] | null; };

// Readonly (this is how Readonly works) type MyReadonly<T> = { readonly [K in keyof T]: T[K]; };

Conditional Types advanced
Types that depend on a condition.
type IsString<T> = T extends string ? "yes" : "no";

type A = IsString<string>; // “yes” type B = IsString<number>; // “no”

// Practical: extract array element type type ElementOf<T> = T extends (infer E)[] ? E : never; type X = ElementOf<string[]>; // string

Template Literal Types advanced
Build string types from other types.
type Color = "red" | "blue";
type Size = "sm" | "lg";
type ClassName = `${Size}-${Color}`;
// "sm-red" | "sm-blue" | "lg-red" | "lg-blue"

type EventName = on${Capitalize&lt;string&gt;}; // “onClick”, “onHover”, etc.

type Getter<T extends string> = get${Capitalize&lt;T&gt;}; type NameGetter = Getter<“name”>; // “getName”


Quick Reference Table

FeatureSyntax
String typelet s: string = "hi"
Arraylet a: number[] = [1, 2]
Tuplelet t: [string, number]
Interfaceinterface User { name: string }
Type aliastype ID = string | number
Unionstring | number
IntersectionTypeA & TypeB
Genericfunction fn<T>(x: T): T
PartialPartial<User>
PickPick<User, "name">
OmitOmit<User, "age">
RecordRecord<string, number>
ReadonlyReadonly<User>
Type guardif (typeof x === "string")
Assertionvalue as Type
Mapped type{ [K in keyof T]: ... }
ConditionalT extends U ? A : B
Template literal`${A}-${B}`