← Back to all guides

TypeScript TLDR

A rapid reference guide to TypeScript. JavaScript with syntax for types.

v5.9 — December 2025

What is TypeScript?

TypeScript is a strongly typed superset of JavaScript that compiles to plain JavaScript. It adds optional static typing, classes, and interfaces to help you build robust applications.

Static Typing

Catch errors at compile time instead of runtime. Type checking helps prevent bugs before they happen.

JavaScript Compatible

Any valid JavaScript is valid TypeScript. Migrate incrementally at your own pace.

Modern Features

Use the latest ECMAScript features and compile down to older JavaScript versions.

Great Tooling

Excellent IDE support with IntelliSense, refactoring, and auto-completion everywhere.

Basics

Type Annotations

// Variable annotations
let name: string = "Alice";
let age: number = 30;
let isActive: boolean = true;

// Type inference (TypeScript infers the type)
let message = "Hello";  // inferred as string
let count = 42;        // inferred as number

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

// Const (immutable reference)
const PI: number = 3.14159;

Type Assertion

// as syntax (preferred)
let value: unknown = "hello";
let length: number = (value as string).length;

// angle-bracket syntax
let length2: number = <string>value.length;

// Non-null assertion (use with caution)
let element = document.getElementById("myId")!;

Any vs Unknown

// any: opt-out of type checking (avoid when possible)
let anything: any = 42;
anything = "now a string";
anything.nonExistentMethod();  // no error!

// unknown: type-safe any (prefer this)
let value: unknown = 42;
// value.toFixed(); // Error: must check type first

if (typeof value === "number") {
    value.toFixed(2);  // OK
}

Types

Primitive Types

Type Description Example
string Text values "hello", 'world', `template`
number Integers and floats 42, 3.14, NaN, Infinity
boolean True or false true, false
null Intentional absence null
undefined Uninitialized value undefined
symbol Unique identifier Symbol("id")
bigint Large integers 100n

Special Types

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

// never: function never returns
function throwError(message: string): never {
    throw new Error(message);
}

// object: any non-primitive type
let obj: object = { name: "Alice" };

Tuples & Enums

// Tuple: fixed-length array with known types
let tuple: [string, number] = ["Alice", 30];
let first = tuple[0];  // string
let second = tuple[1]; // number

// Optional tuple elements
let optional: [string, number?] = ["Bob"];

// Enum: named constants
enum Direction {
    Up,      // 0
    Down,    // 1
    Left,    // 2
    Right    // 3
}

// String enum
enum Status {
    Active = "ACTIVE",
    Inactive = "INACTIVE",
    Pending = "PENDING"
}

let dir: Direction = Direction.Up;
let status: Status = Status.Active;

Literal Types

// String literals
let alignment: "left" | "center" | "right" = "center";

// Numeric literals
let dice: 1 | 2 | 3 | 4 | 5 | 6 = 3;

// Boolean literal
let isTrue: true = true;

Interfaces & Types

Interfaces

// Basic interface
interface User {
    name: string;
    age: number;
    email?: string;        // optional property
    readonly id: number;  // readonly property
}

let user: User = {
    name: "Alice",
    age: 30,
    id: 1
};

// user.id = 2; // Error: readonly

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

let map: StringMap = {
    firstName: "Alice",
    lastName: "Smith"
};

Extending Interfaces

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

interface Employee extends Person {
    employeeId: number;
    department: string;
}

let employee: Employee = {
    name: "Bob",
    age: 25,
    employeeId: 123,
    department: "Engineering"
};

Type Aliases

// Basic type alias
type ID = string | number;

// Object type
type Point = {
    x: number;
    y: number;
};

// Union types
type Status = "success" | "error" | "loading";

// Intersection types
type Draggable = {
    drag: () => void;
};

type Resizable = {
    resize: () => void;
};

type UIWidget = Draggable & Resizable;

Interface vs Type

Use interfaces for object shapes and when you need declaration merging. Use type aliases for unions, intersections, primitives, tuples, and advanced type compositions.

Functions

Function Types

// 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 log(message: string, level: string = "info"): void {
    console.log(`[${level}] ${message}`);
}

Rest Parameters & Overloads

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

// Function overloads
function format(value: string): string;
function format(value: number): string;
function format(value: string | number): string {
    return String(value);
}

Function Types

// Function type annotation
let mathOp: (a: number, b: number) => number;

mathOp = (x, y) => x + y;

// Callback types
function processArray(
    arr: number[],
    callback: (item: number) => number
): number[] {
    return arr.map(callback);
}

// Type alias for function
type Predicate<T> = (value: T) => boolean;

Classes

Basic Class

class Person {
    // Properties
    name: string;
    age: number;
    private ssn: string;           // only accessible in class
    protected address: string;     // accessible in subclasses
    readonly id: number;          // cannot be changed

    // Constructor
    constructor(name: string, age: number, id: number) {
        this.name = name;
        this.age = age;
        this.id = id;
    }

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

    // Static method
    static create(name: string): Person {
        return new Person(name, 0, 0);
    }
}

Parameter Properties

// Shorthand: declares and assigns in one go
class User {
    constructor(
        public name: string,
        private age: number,
        readonly id: number
    ) {}

    getAge(): number {
        return this.age;
    }
}

Inheritance & Abstract Classes

// Abstract class (cannot be instantiated)
abstract class Animal {
    constructor(public name: string) {}

    // Abstract method (must be implemented)
    abstract makeSound(): void;

    // Concrete method
    move(): void {
        console.log(`${this.name} moves`);
    }
}

class Dog extends Animal {
    makeSound(): void {
        console.log("Woof!");
    }
}

let dog = new Dog("Buddy");
dog.makeSound();
dog.move();

Implementing Interfaces

interface Drawable {
    draw(): void;
}

interface Resizable {
    resize(scale: number): void;
}

class Rectangle implements Drawable, Resizable {
    constructor(
        public width: number,
        public height: number
    ) {}

    draw(): void {
        console.log("Drawing rectangle");
    }

    resize(scale: number): void {
        this.width *= scale;
        this.height *= scale;
    }
}

Generics

Generic Functions

// Basic generic function
function identity<T>(value: T): T {
    return value;
}

let result = identity<string>("hello");  // explicit
let result2 = identity(42);           // inferred

// Multiple type parameters
function pair<K, V>(key: K, value: V): [K, V] {
    return [key, value];
}

let p = pair("age", 30);  // [string, number]

Generic Interfaces & Classes

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

let stringBox: Box<string> = { value: "hello" };
let numberBox: Box<number> = { value: 42 };

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

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

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

let stack = new Stack<number>();
stack.push(1);
stack.push(2);

Generic Constraints

// Constrain to types with length property
interface HasLength {
    length: number;
}

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

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

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

let user = { name: "Alice", age: 30 };
let name = getProperty(user, "name");  // OK
// let invalid = getProperty(user, "invalid"); // Error

Utility Types

Built-in Utility Types

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

// Partial<T>: all properties optional
type PartialUser = Partial<User>;
let updates: PartialUser = { name: "Bob" };

// Required<T>: all properties required
type RequiredUser = Required<PartialUser>;

// Readonly<T>: all properties readonly
type ReadonlyUser = Readonly<User>;
let user: ReadonlyUser = { id: 1, name: "Alice", email: "a@b.com", age: 30 };
// user.name = "Bob"; // Error: readonly

// Pick<T, K>: select properties
type UserPreview = Pick<User, "id" | "name">;

// Omit<T, K>: exclude properties
type UserWithoutEmail = Omit<User, "email">;

More Utility Types

// Record<K, T>: object with keys K and values T
type Roles = Record<"admin" | "user" | "guest", string[]>;
let permissions: Roles = {
    admin: ["read", "write", "delete"],
    user: ["read", "write"],
    guest: ["read"]
};

// Exclude<T, U>: exclude types from union
type T0 = Exclude<"a" | "b" | "c", "a">;  // "b" | "c"

// Extract<T, U>: extract types from union
type T1 = Extract<"a" | "b" | "c", "a" | "f">;  // "a"

// NonNullable<T>: exclude null and undefined
type T2 = NonNullable<string | null | undefined>;  // string

// ReturnType<T>: get function return type
function getUser() {
    return { name: "Alice", age: 30 };
}
type User2 = ReturnType<typeof getUser>;

Advanced Types

Union & Intersection Types

// Union: value can be one of several types
type StringOrNumber = string | number;

function format(value: StringOrNumber): string {
    if (typeof value === "string") {
        return value.toUpperCase();
    }
    return value.toFixed(2);
}

// Intersection: combine multiple types
type Named = { name: string };
type Aged = { age: number };
type Person = Named & Aged;

let person: Person = { name: "Alice", age: 30 };

Type Guards

// typeof guard
function print(value: string | number): void {
    if (typeof value === "string") {
        console.log(value.toUpperCase());
    } else {
        console.log(value.toFixed(2));
    }
}

// instanceof guard
class Dog {
    bark() { console.log("Woof!"); }
}
class Cat {
    meow() { console.log("Meow!"); }
}

function makeSound(animal: Dog | Cat): void {
    if (animal instanceof Dog) {
        animal.bark();
    } else {
        animal.meow();
    }
}

// Custom type guard
interface Fish {
    swim(): void;
}
interface Bird {
    fly(): void;
}

function isFish(animal: Fish | Bird): animal is Fish {
    return (animal as Fish).swim !== undefined;
}

Conditional Types

// T extends U ? X : Y
type IsString<T> = T extends string ? "yes" : "no";

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

// Distributive conditional types
type ToArray<T> = T extends any ? T[] : never;

type StrOrNum = ToArray<string | number>;  // string[] | number[]

Mapped Types

// Make all properties optional
type MyPartial<T> = {
    [P in keyof T]?: T[P];
};

// Make all properties readonly
type MyReadonly<T> = {
    readonly [P in keyof T]: T[P];
};

// Map to different type
type Stringify<T> = {
    [P in keyof T]: string;
};

Template Literal Types

// String manipulation in types
type Greeting = `hello ${"world" | "TypeScript"}`;
// "hello world" | "hello TypeScript"

// Uppercase/Lowercase utility types
type Upper = Uppercase<"hello">;  // "HELLO"
type Lower = Lowercase<"HELLO">;  // "hello"
type Cap = Capitalize<"hello">;    // "Hello"
type Uncap = Uncapitalize<"Hello">;  // "hello"

Configuration & Tooling

tsconfig.json

{
  "compilerOptions": {
    // Target JavaScript version
    "target": "ES2022",
    "module": "ESNext",
    "lib": ["ES2022", "DOM"],

    // Module resolution
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "esModuleInterop": true,

    // Output
    "outDir": "./dist",
    "rootDir": "./src",
    "declaration": true,
    "sourceMap": true,

    // Strictness
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "noUncheckedIndexedAccess": true,

    // Additional checks
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

Common CLI Commands

# Install TypeScript
npm install -g typescript

# Initialize tsconfig.json
tsc --init

# Compile TypeScript files
tsc
tsc file.ts
tsc --watch

# Type checking only (no output)
tsc --noEmit

# Show version
tsc --version

Type Declarations

// .d.ts declaration files
// Install types for libraries
// npm install --save-dev @types/node
// npm install --save-dev @types/react

// Declare global variables
declare const API_URL: string;

// Declare modules without types
declare module "*.css" {
    const content: { [className: string]: string };
    export default content;
}

// Ambient declarations
declare namespace MyLib {
    function greet(name: string): void;
}
Enable strict: true in tsconfig.json for maximum type safety. Start strict from day one for new projects.