Skip to main content
TautCoder
EditReport

TypeScript Cheatsheet

This page is a quick reference for TypeScript patterns that show up constantly in DSA and competitive programming. TypeScript adds static typing to JavaScript, catching errors at compile time. If you're just starting out, don't worry, every snippet here is explained line by line 😊

Type Annotations

Basic Types

Basic type annotations in TypeScript
let num: number = 42;           // Number type
let str: string = "hello"; // String type
let bool: boolean = true; // Boolean type
let nothing: null = null; // Null type
let undef: undefined = undefined; // Undefined type

// Type inference (TypeScript infers type automatically)
let x = 5; // x is inferred as number
let y = "text"; // y is inferred as string

Arrays and Tuples

Array and tuple types
let nums: number[] = [1, 2, 3];         // Array of numbers
let strs: Array<string> = ["a", "b"]; // Alternative syntax

// Tuple — fixed-length array with specific types
let pair: [number, string] = [1, "one"];
let triple: [number, number, number] = [1, 2, 3];

// Array of tuples
let pairs: [number, string][] = [[1, "one"], [2, "two"]];

Objects

Object type annotations
// Inline object type
let point: { x: number; y: number } = { x: 10, y: 20 };

// Optional properties
let user: { name: string; age?: number } = { name: "Alice" }; // age is optional

// Readonly properties
let config: { readonly apiKey: string } = { apiKey: "secret" };
// config.apiKey = "new"; // Error — cannot modify readonly property

Interfaces and Type Aliases

Interfaces

Interface definitions
interface Point {
x: number;
y: number;
}

const p: Point = { x: 5, y: 10 };

// Optional properties
interface User {
name: string;
age?: number; // Optional
readonly id: number; // Readonly
}

// Extending interfaces
interface Shape {
area(): number;
}

interface Circle extends Shape {
radius: number;
}

const circle: Circle = {
radius: 5,
area() {
return Math.PI * this.radius ** 2;
}
};

Type Aliases

Type alias definitions
type ID = number | string;      // Union type
type Point = { x: number; y: number };

let userId: ID = 123; // Can be number
userId = "abc"; // Or string

// Function type
type BinaryOp = (a: number, b: number) => number;

const add: BinaryOp = (a, b) => a + b;
const multiply: BinaryOp = (a, b) => a * b;

Interface vs Type Alias

When to use interface vs type
// Use interface for object shapes (can be extended)
interface Animal {
name: string;
}

interface Dog extends Animal {
breed: string;
}

// Use type for unions, intersections, primitives
type Status = "pending" | "success" | "error"; // Union
type Coordinate = [number, number]; // Tuple
type Nullable<T> = T | null; // Generic

Union and Intersection Types

Union Types

Union type examples
// Variable can be one of multiple types
let value: number | string;
value = 42; // Valid
value = "hello"; // Valid
// value = true; // Error

// Array of mixed types
let mixed: (number | string)[] = [1, "two", 3, "four"];

// Function with union parameter
function print(val: number | string): void {
console.log(val);
}

Intersection Types

Intersection type examples
// Combines multiple types
type Person = { name: string };
type Employee = { id: number };

type Worker = Person & Employee; // Must have both name and id

const worker: Worker = {
name: "Alice",
id: 123
};

Type Guards

Narrowing Types

Type guard patterns
function process(val: number | string) {
if (typeof val === "string") {
// TypeScript knows val is string here
console.log(val.toUpperCase());
} else {
// TypeScript knows val is number here
console.log(val.toFixed(2));
}
}

// Array type guard
function sum(arr: number[] | string) {
if (Array.isArray(arr)) {
return arr.reduce((a, b) => a + b, 0);
}
return parseInt(arr);
}

// Null/undefined check
function getLength(s: string | null): number {
if (s === null) return 0;
return s.length; // TypeScript knows s is string here
}

Custom Type Guards

Custom type guard functions
interface Cat {
meow(): void;
}

interface Dog {
bark(): void;
}

// Type predicate
function isCat(animal: Cat | Dog): animal is Cat {
return (animal as Cat).meow !== undefined;
}

function makeSound(animal: Cat | Dog) {
if (isCat(animal)) {
animal.meow(); // TypeScript knows it's Cat
} else {
animal.bark(); // TypeScript knows it's Dog
}
}

Generics

Generic Functions

Generic function examples
// Generic identity function
function identity<T>(arg: T): T {
return arg;
}

let num = identity<number>(42); // Explicit type
let str = identity("hello"); // Type inferred

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

const person = { name: "Alice", age: 30 };
const name = getProperty(person, "name"); // Type is string
const age = getProperty(person, "age"); // Type is number

Generic Interfaces and Classes

Generic interfaces and classes
// Generic interface
interface Box<T> {
value: T;
}

const numBox: Box<number> = { value: 42 };
const strBox: Box<string> = { value: "hello" };

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

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

pop(): T | undefined {
return this.items.pop();
}

peek(): T | undefined {
return this.items[this.items.length - 1];
}
}

const numStack = new Stack<number>();
numStack.push(1);
numStack.push(2);

Generic Constraints

Generic constraints
// Constraint: T must have length property
interface HasLength {
length: number;
}

function logLength<T extends HasLength>(arg: T): void {
console.log(arg.length);
}

logLength("hello"); // Valid — string has length
logLength([1, 2, 3]); // Valid — array has length
// logLength(42); // Error — number doesn't have length

Utility Types

Common Built-in Utility Types

TypeScript utility types
interface User {
id: number;
name: string;
email: string;
}

// Partial — makes all properties optional
type PartialUser = Partial<User>;
const user1: PartialUser = { name: "Alice" }; // Valid

// Required — makes all properties required
type RequiredUser = Required<PartialUser>;

// Readonly — makes all properties readonly
type ReadonlyUser = Readonly<User>;
const user2: ReadonlyUser = { id: 1, name: "Bob", email: "bob@example.com" };
// user2.name = "Alice"; // Error — readonly

// Pick — select specific properties
type UserPreview = Pick<User, "id" | "name">;
const preview: UserPreview = { id: 1, name: "Alice" };

// Omit — exclude specific properties
type UserWithoutEmail = Omit<User, "email">;
const user3: UserWithoutEmail = { id: 1, name: "Alice" };

// Record — create object type with specific keys and value type
type Scores = Record<string, number>;
const scores: Scores = { math: 90, english: 85 };

Function Types

Function Signatures

Function type annotations
// Function declaration
function add(a: number, b: number): number {
return a + b;
}

// Arrow function
const multiply = (a: number, b: number): number => a * b;

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

// Default parameters
function power(base: number, exponent: number = 2): number {
return base ** exponent;
}

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

Function Overloads

Function overloading
// Overload signatures
function process(x: number): number;
function process(x: string): string;
function process(x: number[]): number;

// Implementation signature
function process(x: number | string | number[]): number | string {
if (typeof x === "number") {
return x * 2;
} else if (typeof x === "string") {
return x.toUpperCase();
} else {
return x.reduce((a, b) => a + b, 0);
}
}

process(5); // Returns number
process("hello"); // Returns string
process([1, 2, 3]); // Returns number

Classes

Class Syntax

Class definitions in TypeScript
class Point {
x: number;
y: number;

constructor(x: number, y: number) {
this.x = x;
this.y = y;
}

distance(): number {
return Math.sqrt(this.x ** 2 + this.y ** 2);
}
}

const p = new Point(3, 4);
console.log(p.distance()); // 5

Access Modifiers

Access modifiers in classes
class BankAccount {
public owner: string; // Accessible everywhere (default)
private balance: number; // Only accessible within class
protected accountNumber: string; // Accessible in class and subclasses

constructor(owner: string, balance: number, accountNumber: string) {
this.owner = owner;
this.balance = balance;
this.accountNumber = accountNumber;
}

deposit(amount: number): void {
this.balance += amount;
}

getBalance(): number {
return this.balance;
}
}

const account = new BankAccount("Alice", 1000, "123");
console.log(account.owner); // Valid
// console.log(account.balance); // Error — private
console.log(account.getBalance()); // Valid — public method

Shorthand Constructor

Constructor parameter properties
class Point {
// Shorthand — declares and initializes properties
constructor(public x: number, public y: number) {}

distance(): number {
return Math.sqrt(this.x ** 2 + this.y ** 2);
}
}

const p = new Point(3, 4); // x and y are automatically assigned

Abstract Classes

Abstract classes in TypeScript
abstract class Shape {
abstract area(): number; // Must be implemented by subclasses

describe(): string { // Concrete method
return `Area: ${this.area()}`;
}
}

class Circle extends Shape {
constructor(public radius: number) {
super();
}

area(): number {
return Math.PI * this.radius ** 2;
}
}

const circle = new Circle(5);
console.log(circle.describe()); // "Area: 78.54..."

Enums

Numeric Enums

Numeric enum examples
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right // 3
}

let dir: Direction = Direction.Up;

// Custom starting value
enum Status {
Pending = 1,
Success = 2,
Error = 3
}

String Enums

String enum examples
enum Color {
Red = "RED",
Green = "GREEN",
Blue = "BLUE"
}

let color: Color = Color.Red;
console.log(color); // "RED"

Const Enums

Const enums for performance
const enum Direction {
Up,
Down,
Left,
Right
}

let dir = Direction.Up; // Inlined at compile time, no runtime object

Type Assertions

As Syntax

Type assertions in TypeScript
// Tell TypeScript to treat value as specific type
let value: unknown = "hello";
let length: number = (value as string).length;

// Alternative syntax (not recommended in JSX)
let length2: number = (<string>value).length;

// Non-null assertion
function getElement(id: string): HTMLElement | null {
return document.getElementById(id);
}

const elem = getElement("myId")!; // Assert it's not null
elem.innerHTML = "Hello";

Async/Await with Types

Promise Types

Typed promises
// Function returning Promise
async function fetchData(): Promise<string> {
const response = await fetch("https://api.example.com/data");
const data = await response.text();
return data;
}

// Generic Promise
async function fetchJSON<T>(url: string): Promise<T> {
const response = await fetch(url);
return response.json();
}

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

const user = await fetchJSON<User>("https://api.example.com/user");
console.log(user.name); // TypeScript knows user has name property

Common DSA Patterns with Types

Typed Data Structures

Type-safe data structures
// Stack
class Stack<T> {
private items: T[] = [];

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

pop(): T | undefined {
return this.items.pop();
}

isEmpty(): boolean {
return this.items.length === 0;
}
}

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

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

dequeue(): T | undefined {
return this.items.shift();
}
}

// Binary Tree Node
class TreeNode<T> {
constructor(
public value: T,
public left: TreeNode<T> | null = null,
public right: TreeNode<T> | null = null
) {}
}

Graph Representation

Typed graph structures
// Adjacency list with Map
type Graph<T> = Map<T, T[]>;

function createGraph<T>(): Graph<T> {
return new Map();
}

function addEdge<T>(graph: Graph<T>, from: T, to: T): void {
if (!graph.has(from)) {
graph.set(from, []);
}
graph.get(from)!.push(to);
}

// Weighted graph
interface Edge<T> {
to: T;
weight: number;
}

type WeightedGraph<T> = Map<T, Edge<T>[]>;

Algorithm Return Types

Typed algorithm functions
// Binary search
function binarySearch(arr: number[], target: number): number {
let left = 0, right = arr.length - 1;

while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (arr[mid] === target) return mid;
if (arr[mid] < target) left = mid + 1;
else right = mid - 1;
}
return -1;
}

// Two sum with tuple return
function twoSum(nums: number[], target: number): [number, number] | null {
const map = new Map<number, number>();

for (let i = 0; i < nums.length; i++) {
const complement = target - nums[i];
if (map.has(complement)) {
return [map.get(complement)!, i];
}
map.set(nums[i], i);
}
return null;
}

Type Narrowing Patterns

Discriminated Unions

Discriminated union pattern
interface Success {
type: "success";
data: string;
}

interface Error {
type: "error";
message: string;
}

type Result = Success | Error;

function handleResult(result: Result): void {
if (result.type === "success") {
console.log(result.data); // TypeScript knows it's Success
} else {
console.log(result.message); // TypeScript knows it's Error
}
}

Configuration

tsconfig.json Essentials

Recommended tsconfig.json for DSA
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}

References

Finished reading? Mark this topic as complete.