🔷 TypeScript
TypeScript Complete Cheatsheet
Types, interfaces, generics, utility types — complete TypeScript for JavaScript developers.
📖 10 sections
⏱ 22 min read
✅ Quizzes included
🌙 Dark mode
01 Types & Variables
TSTypeScript basic types
// Primitives
let name: string = 'Ali';
let age: number = 22;
let active: boolean = true;
let id: bigint = 100n;
let sym: symbol = Symbol('key');

// Any, unknown, never, void
let anything: any = 'whatever';       // opt out of type checking
let safe: unknown = 'check first';    // must narrow before using
function throws(): never { throw new Error(); }  // never returns
function log(): void { console.log('hi'); }

// Arrays and tuples
let nums: number[] = [1, 2, 3];
let strs: Array = ['a', 'b'];
let pair: [string, number] = ['Ali', 22];  // tuple: fixed types

// Type inference (TypeScript infers when obvious)
let x = 42;        // inferred as number
const msg = 'hi';  // inferred as 'hi' (literal type)
💡
Prefer 'unknown' over 'any'. unknown forces you to narrow the type before using it, keeping type safety.
02 Functions
TSFunction typing
// Parameter and return types
function greet(name: string, age: number = 0): string {
  return `Hello ${name}, age ${age}`;
}

// Arrow function
const add = (a: number, b: number): number => a + b;

// Optional parameters
function log(msg: string, level?: string): void {
  console.log(`[${level ?? 'INFO'}] ${msg}`);
}

// Rest parameters
const sum = (...nums: number[]): number => nums.reduce((a,b) => a+b, 0);

// Function overloads
function format(val: string): string;
function format(val: number, decimals: number): string;
function format(val: string | number, decimals?: number): string {
  if (typeof val === 'number') return val.toFixed(decimals ?? 2);
  return val.toUpperCase();
}

// Callback typing
function fetchData(callback: (err: Error | null, data?: User) => void): void {}
void
Function returns nothing
never
Function never completes normally (throws or infinite loop)
Async function
async function fetchUser(id: number): Promise
03 Interfaces & Types
TSInterfaces and type aliases
// Interface
interface User {
  id: number;
  name: string;
  email?: string;           // optional
  readonly createdAt: Date; // can't be changed after creation
}

// Extend interface
interface AdminUser extends User {
  permissions: string[];
}

// Type alias
type Point = { x: number; y: number };
type ID = string | number;  // union type
type Status = 'active' | 'inactive' | 'pending';

// Index signature
interface StringMap {
  [key: string]: string;
}

// Interface for functions
interface Transformer {
  (input: string): string;
}
const upper: Transformer = (s) => s.toUpperCase();
interface
Can be reopened/extended multiple times (declaration merging)
type
More powerful — unions, intersections, mapped types, conditional types
When to use
Prefer interface for objects/classes. Use type for unions, primitives, utility types.
04 Classes
TSClasses
class Animal {
  protected name: string;  // accessible in subclasses
  private age: number;      // only this class
  readonly species: string; // can't change after set

  constructor(name: string, age: number, species: string) {
    this.name = name;
    this.age = age;
    this.species = species;
  }

  // Getter/setter
  get info(): string { return `${this.name} (${this.age})`; }
  set setAge(age: number) { if (age > 0) this.age = age; }

  speak(): string { return `${this.name} makes a sound`; }
}

class Dog extends Animal {
  constructor(name: string, age: number) {
    super(name, age, 'Canis lupus');  // must call super first
  }
  speak(): string { return `${this.name} barks`; }
}

// Implement interface
interface Printable { print(): void; }
class Doc implements Printable {
  print() { console.log('printing...'); }
}
05 Generics
TSGenerics
// Generic function
function identity(arg: T): T { return arg; }
identity('hello');  // explicit
identity(42);               // inferred

// Generic with constraint
function getLength(arg: T): number {
  return arg.length;
}

// Generic interface
interface ApiResponse {
  data: T;
  error: string | null;
  status: number;
}

// Generic class
class Stack {
  private items: T[] = [];
  push(item: T): void { this.items.push(item); }
  pop(): T | undefined { return this.items.pop(); }
  get size(): number { return this.items.length; }
}

// Multiple type params
function pair(key: K, val: V): [K, V] {
  return [key, val];
}
💡
Use generics to write reusable, type-safe code. Prefer T extends SomeType over any when you know the constraint.
06 Utility Types
TSBuilt-in utility types
interface User { id: number; name: string; email: string; role: string; }

Partial         // all fields optional
Required        // all fields required
Readonly        // all fields readonly

Pick        // only id and name
Omit           // all except password

Record             // {[key: string]: User}
Record<'admin' | 'user', User>   // specific keys

Exclude<'a' | 'b' | 'c', 'a'>  // 'b' | 'c'
Extract<'a' | 'b' | 'c', 'a' | 'b'>  // 'a' | 'b'

NonNullable  // string

ReturnType     // get function return type
Parameters         // get function param types

Await>          // string
Partial
Makes all properties optional — great for update DTOs
Pick/Omit
Select/exclude specific fields — great for form types
Record
Build dictionary types with specific value types
07 Enums
TSEnums
// Numeric enum (default)
enum Direction { Up, Down, Left, Right }  // Up=0, Down=1...
const d: Direction = Direction.Up;

// String enum (preferred — more debuggable)
enum Status {
  Active = 'ACTIVE',
  Inactive = 'INACTIVE',
  Pending = 'PENDING'
}

// Const enum (inlined at compile time — no JS object)
const enum Color { Red, Green, Blue }

// Alternative: use 'as const' instead of enum
const STATUS = {
  Active: 'ACTIVE',
  Inactive: 'INACTIVE'
} as const;

type Status = typeof STATUS[keyof typeof STATUS];  // 'ACTIVE' | 'INACTIVE'
💡
Many TypeScript experts recommend 'as const' objects over enums. They work better with tree-shaking and don't generate extra JS code.
08 Union & Intersection
TSUnion, intersection, narrowing
// Union types
type ID = string | number;
type Result = { success: true; data: User } | { success: false; error: string };

// Intersection types
type Admin = User & { permissions: string[] };

// Type narrowing
function process(input: string | number) {
  if (typeof input === 'string') {
    return input.toUpperCase();  // TS knows it's string here
  }
  return input.toFixed(2);      // TS knows it's number here
}

// Discriminated unions
type Shape =
  | { kind: 'circle'; radius: number }
  | { kind: 'square'; side: number };

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

// Type guard
function isUser(obj: unknown): obj is User {
  return typeof obj === 'object' && obj !== null && 'id' in obj;
}
09 Modules & Config
TStsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",           // output JS version
    "module": "commonjs",         // module system
    "lib": ["ES2020", "DOM"],      // available APIs
    "outDir": "./dist",            // output directory
    "rootDir": "./src",            // source directory
    "strict": true,               // enable all strict checks
    "noImplicitAny": true,         // no implicit any
    "strictNullChecks": true,      // null safety
    "esModuleInterop": true,       // better imports
    "skipLibCheck": true,          // skip .d.ts checking
    "forceConsistentCasingInFileNames": true,
    "declaration": true,           // generate .d.ts files
    "sourceMap": true              // source maps for debugging
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}
💡
Always enable 'strict: true' in new projects. It enables strictNullChecks, noImplicitAny, and other critical safety checks.
10 Mini Quizzes
❓ Quiz 1
What is the difference between 'any' and 'unknown'?
any turns off type checking completely. unknown forces you to check the type first (typeof, instanceof, type guard). Always prefer unknown over any.
❓ Quiz 2
What does Partial do?
Partial creates a type where all properties of T are optional (marked with ?). Useful for update/patch operations where not all fields are required.