TypeScript logo
TypeScript Cheatsheet
19 of 19 code examples
.ts
Basic Types
Type annotations
Types
let name: string = "Alice";
let age: number = 30;
let isActive: boolean = true;
let data: null = null;

// Arrays
let numbers: number[] = [1, 2, 3];
let names: Array<string> = ["Alice", "Bob"];

// Tuples
let person: [string, number] = ["Alice", 30];

// Union types
let id: string | number = "123";
id = 456; // Valid
Interfaces
Object shapes
Types
interface User {
  id: number;
  name: string;
  email?: string;        // Optional
  readonly createdAt: Date;
}

// Usage
let user: User = {
  id: 1,
  name: "Alice",
  createdAt: new Date()
};

// Extending
interface Admin extends User {
  permissions: string[];
}
Functions
Typed functions
Functions
// Basic function
function add(a: number, b: number): number {
  return a + b;
}

// Arrow function
const multiply = (x: number, y: number): number => x * y;

// Optional parameters
function greet(name: string, greeting?: string): string {
  return `${greeting || "Hello"}, ${name}!`;
}

// Generic function
function identity<T>(arg: T): T {
  return arg;
}
Classes
OOP with types
Classes
class Person {
  private name: string;
  protected age: number;
  public email: string;

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

  greet(): string {
    return `Hello, I'm ${this.name}`;
  }
}

class Student extends Person {
  private grade: string;

  constructor(name: string, age: number, email: string, grade: string) {
    super(name, age, email);
    this.grade = grade;
  }
}
Generics
Generic types
Advanced
// Generic function
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

// Generic interface
interface Repository<T> {
  findById(id: string): T | null;
  save(entity: T): void;
}

// Generic class
class Collection<T> {
  private items: T[] = [];

  add(item: T): void {
    this.items.push(item);
  }

  get(index: number): T | undefined {
    return this.items[index];
  }
}
Utility Types
Built-in utilities
Advanced
interface User {
  id: number;
  name: string;
  email: string;
  age: number;
}

// Common utilities
type PartialUser = Partial<User>;        // All optional
type RequiredUser = Required<User>;      // All required
type UserEmail = Pick<User, 'email'>;    // Pick specific
type UserWithoutId = Omit<User, 'id'>;   // Exclude specific

// Record type
type UserRoles = Record<string, string>;
const roles: UserRoles = {
  admin: "Administrator",
  user: "Regular User"
};
Type Guards
Runtime type checking
Advanced
// Type guard
function isString(value: unknown): value is string {
  return typeof value === 'string';
}

function isUser(value: unknown): value is User {
  return (
    typeof value === 'object' &&
    value !== null &&
    'id' in value &&
    'name' in value
  );
}

// Discriminated unions
type Shape = 
  | { kind: 'circle'; radius: number }
  | { kind: 'rectangle'; width: number; height: number };

function getArea(shape: Shape): number {
  switch (shape.kind) {
    case 'circle':
      return Math.PI * shape.radius * shape.radius;
    case 'rectangle':
      return shape.width * shape.height;
  }
}
Modules
Import and export
Modules
// Export
export const PI = 3.14159;
export function add(a: number, b: number): number {
  return a + b;
}
export default class Calculator {}

// Import
import Calculator, { PI, add } from './math';
import * as Math from './math';

// Type-only imports
import type { User } from './types';
Error Handling
Typed errors
Error Handling
// Custom error
class ApiError extends Error {
  constructor(
    message: string,
    public statusCode: number
  ) {
    super(message);
    this.name = 'ApiError';
  }
}

// Result type
type Result<T, E = Error> = 
  | { success: true; data: T }
  | { success: false; error: E };

function divide(a: number, b: number): Result<number> {
  if (b === 0) {
    return {
      success: false,
      error: new Error("Cannot divide by zero")
    };
  }
  
  return {
    success: true,
    data: a / b
  };
}
Mapped Types
Type transformations
Advanced
// Basic mapped types
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

type Partial<T> = {
  [P in keyof T]?: T[P];
};

// Key remapping
type Getters<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};

interface User {
  name: string;
  age: number;
}

type UserGetters = Getters<User>; 
// { getName: () => string; getAge: () => number; }
Conditional Types
Type-level logic
Advanced
// Basic conditional
type IsString<T> = T extends string ? true : false;

// Infer keyword
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
type MyFunc = () => string;
type MyReturn = ReturnType<MyFunc>; // string

// Array element type
type ArrayElement<T> = T extends (infer U)[] ? U : never;

// Promise unwrapping
type Awaited<T> = T extends Promise<infer U> ? U : T;
Template Literal Types
String pattern types
Advanced
// Basic templates
type Greeting = `Hello ${string}`;
type EventName<T extends string> = `on${Capitalize<T>}`;
type ClickEvent = EventName<'click'>; // 'onClick'

// CSS properties
type CSSProperty<T extends string> = `--${T}`;
type PrimaryColor = CSSProperty<'primary-color'>;

// API endpoints
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type ApiEndpoint<M extends HttpMethod, P extends string> = `/${M}/${P}`;
type GetUsers = ApiEndpoint<'GET', 'users'>;
Branded Types
Distinct primitive types
Advanced
// Branded types
type UserId = string & { __brand: 'UserId' };
type ProductId = string & { __brand: 'ProductId' };

function createUserId(id: string): UserId {
  return id as UserId;
}

// Type safety
function getUser(id: UserId) { /* ... */ }

const userId = createUserId('123');
const productId = '456' as ProductId;

getUser(userId); // OK
// getUser(productId); // Error!
Decorators
Method and class decorators
Advanced
// Method decorator
function Log(target: any, propertyName: string, descriptor: PropertyDescriptor) {
  const method = descriptor.value;
  
  descriptor.value = function (...args: any[]) {
    console.log(`Calling ${propertyName}`);
    return method.apply(this, args);
  };
}

class Calculator {
  @Log
  add(a: number, b: number): number {
    return a + b;
  }
}

// Property decorator
function MinLength(length: number) {
  return function (target: any, propertyName: string) {
    // Validation logic here
  };
}
Real-World: API Client
Typed HTTP client
Real World
interface ApiResponse<T> {
  data: T;
  message: string;
  status: 'success' | 'error';
}

class ApiClient {
  async get<T>(endpoint: string): Promise<ApiResponse<T>> {
    const response = await fetch(endpoint);
    return response.json();
  }

  async post<T, U>(endpoint: string, data: U): Promise<ApiResponse<T>> {
    const response = await fetch(endpoint, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    });
    return response.json();
  }
}

// Usage
const client = new ApiClient();
const user = await client.get<User>('/api/users/123');
Real-World: Form Validation
Type-safe forms
Real World
interface FormData {
  name: string;
  email: string;
  age: number;
}

function validateForm(data: Partial<FormData>): Record<string, string> {
  const errors: Record<string, string> = {};
  
  if (!data.name) errors.name = 'Name required';
  if (!data.email?.includes('@')) errors.email = 'Invalid email';
  if (data.age && data.age < 0) errors.age = 'Age must be positive';
  
  return errors;
}

// Usage
const errors = validateForm({ name: 'Alice', age: -5 });
console.log(errors); // { age: 'Age must be positive' }
Real-World: State Management
Typed Redux pattern
Real World
// Action types
type Action<T extends string, P = void> = P extends void
  ? { type: T }
  : { type: T; payload: P };

type AddTodoAction = Action<'ADD_TODO', { text: string }>;
type ToggleTodoAction = Action<'TOGGLE_TODO', { id: string }>;
type TodoAction = AddTodoAction | ToggleTodoAction;

// Reducer
function todoReducer(state: TodoState, action: TodoAction): TodoState {
  switch (action.type) {
    case 'ADD_TODO':
      return {
        ...state,
        todos: [...state.todos, {
          id: crypto.randomUUID(),
          text: action.payload.text,
          completed: false
        }]
      };
    
    case 'TOGGLE_TODO':
      return {
        ...state,
        todos: state.todos.map(todo =>
          todo.id === action.payload.id
            ? { ...todo, completed: !todo.completed }
            : todo
        )
      };
    
    default:
      return state;
  }
}
keyof and typeof
Type queries
Advanced
interface User {
  id: number;
  name: string;
  email: string;
}

// keyof - get keys as union
type UserKeys = keyof User; // "id" | "name" | "email"

// typeof - get type from value
const user = {
  id: 1,
  name: "Alice",
  email: "alice@example.com"
};

type UserType = typeof user;
// { id: number; name: string; email: string }

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

const userName = getProperty(user, 'name'); // string
Index Signatures
Dynamic object keys
Advanced
// String index signature
interface StringDictionary {
  [key: string]: string;
}

const dict: StringDictionary = {
  name: "Alice",
  email: "alice@example.com"
};

// Number index signature  
interface NumberArray {
  [index: number]: string;
}

const arr: NumberArray = ["apple", "banana"];

// Mixed signatures
interface MixedDictionary {
  [key: string]: any;
  id: number;  // Required property
}

const mixed: MixedDictionary = {
  id: 1,
  name: "Alice",
  data: { age: 30 }
};