TypeScript has become the industry standard for large-scale JavaScript applications. By adding static types, it catches errors early and improves developer experience through better tooling. This guide covers everything from the basics to advanced type system features.
The core building blocks of TypeScript.
let isDone: boolean = false; let decimal: number = 6; let color: string = "blue"; let big: bigint = 100n; let sym: symbol = Symbol("key");
Defining lists and fixed-length collections.
// Arrays let list: number[] = [1, 2, 3]; let listGeneric: Array<number> = [1, 2, 3]; // Generic syntax // Tuples (Fixed length and types) let x: [string, number]; x = ["hello", 10]; // OK // x = [10, "hello"]; // Error
Types for handling unknown or absent values.
// Any: Opt-out of type checking (Avoid when possible) let notSure: any = 4; notSure = "maybe a string instead"; // Unknown: Safer alternative to any let value: unknown = 4; // value.toFixed(); // Error: Object is of type 'unknown'. if (typeof value === "number") { value.toFixed(); // OK } // Void: Absence of return value function warnUser(): void { console.log("This is my warning message"); } // Never: Values that never occur (e.g., infinite loops, errors) function error(message: string): never { throw new Error(message); }
Both can describe shapes of objects, but they have subtle differences.
// Interface: Better for defining object shapes and extending interface User { name: string; id: number; } interface Admin extends User { privileges: string[]; } // Type Alias: Better for unions, primitives, and tuples type ID = string | number; type Status = "active" | "inactive"; type Point = { x: number; y: number; };
Interfaces are "open" and can be merged. Types cannot.
interface Box { height: number; } interface Box { width: number; } const box: Box = { height: 5, width: 6 }; // OK
function add(x: number, y: number): number { return x + y; } // Arrow function syntax const multiply = (x: number, y: number): number => x * y;
function buildName(firstName: string, lastName?: string): string { if (lastName) return firstName + " " + lastName; return firstName; } function buildNameDefault(firstName: string, lastName: string = "Smith"): string { return firstName + " " + lastName; }
Defining multiple signatures for a single function.
function makeDate(timestamp: number): Date; function makeDate(m: number, d: number, y: number): Date; function makeDate(mOrTimestamp: number, d?: number, y?: number): Date { if (d !== undefined && y !== undefined) { return new Date(y, mOrTimestamp, d); } else { return new Date(mOrTimestamp); } }
class Animal { // Shorthand for creating and assigning properties constructor( public name: string, private age: number, protected species: string ) {} public move(distanceInMeters: number = 0) { console.log(`${this.name} moved ${distanceInMeters}m.`); } } class Snake extends Animal { constructor(name: string) { super(name, 5, "Reptile"); // Can access protected 'species' here but not outside } }
Classes that cannot be instantiated directly.
abstract class Department { constructor(public name: string) {} printName(): void { console.log("Department name: " + this.name); } abstract printMeeting(): void; // Must be implemented in derived classes }
Writing reusable code components.
function identity<T>(arg: T): T { return arg; } let output = identity<string>("myString"); let output2 = identity(100); // Type inference
Limiting the types that can be passed to a generic.
interface Lengthwise { length: number; } function loggingIdentity<T extends Lengthwise>(arg: T): T { console.log(arg.length); // Now we know it has a .length property return arg; }
// Union: Value can be one of several types function padLeft(value: string, padding: string | number) { // ... } // Intersection: Combine multiple types into one interface ErrorHandling { success: boolean; error?: { message: string }; } interface ArtworksData { artworks: { title: string }[]; } type ArtworksResponse = ArtworksData & ErrorHandling;
Narrowing down types at runtime.
function isNumber(x: any): x is number { return typeof x === "number"; } function padLeft(value: string, padding: string | number) { if (isNumber(padding)) { return Array(padding + 1).join(" ") + value; } if (typeof padding === "string") { return padding + value; } throw new Error(`Expected string or number, got '${padding}'.`); }
Specifying exact values.
type Easing = "ease-in" | "ease-out" | "ease-in-out"; function animate(dx: number, dy: number, easing: Easing) { // ... }
Built-in types to transform existing types.
interface Todo { title: string; description: string; completed: boolean; } // Partial: Make all properties optional type PartialTodo = Partial<Todo>; // Required: Make all properties required type RequiredTodo = Required<PartialTodo>; // Readonly: Make all properties readonly type ReadonlyTodo = Readonly<Todo>; // Pick: Select a subset of properties type TodoPreview = Pick<Todo, "title" | "completed">; // Omit: Remove a subset of properties type TodoInfo = Omit<Todo, "completed">;
// Record: Construct an object type with specific keys and values type Page = "home" | "about" | "contact"; type PageInfo = { title: string }; const nav: Record<Page, PageInfo> = { about: { title: "about" }, contact: { title: "contact" }, home: { title: "home" }, }; // Exclude: Remove types from a union type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c" // Extract: Keep types that are assignable to another type type T1 = Extract<"a" | "b" | "c", "a" | "f">; // "a" // NonNullable: Remove null and undefined type T2 = NonNullable<string | number | undefined>; // string | number // ReturnType: Get the return type of a function type T3 = ReturnType<() => string>; // string
Creating new types based on old ones.
type OptionsFlags<Type> = { [Property in keyof Type]: boolean; }; type FeatureFlags = { darkMode: () => void; newUserProfile: () => void; }; type FeatureOptions = OptionsFlags<FeatureFlags>; // { darkMode: boolean; newUserProfile: boolean; }
Types that depend on a condition.
type MessageOf<T> = T extends { message: unknown } ? T["message"] : never; interface Email { message: string; } interface Dog { bark(): void; } type EmailMessageContents = MessageOf<Email>; // string type DogMessageContents = MessageOf<Dog>; // never
Building types using string templates.
type World = "world"; type Greeting = `hello ${World}`; // "hello world" type Color = "red" | "blue"; type Quantity = "one" | "two"; type Item = `${Color}-${Quantity}`; // "red-one" | "red-two" | "blue-one" | "blue-two"
keyof and typeof Operators// keyof: Get union of keys interface Person { name: string; age: number; } type PersonKeys = keyof Person; // "name" | "age" // typeof: Get type of a value let s = "hello"; let n: typeof s; // string
Accessing a specific property's type.
type Person = { age: number; name: string; alive: boolean }; type Age = Person["age"]; // number
satisfies OperatorValidates that an expression matches a type, without changing the resulting type of that expression (preserves inference).
type Colors = "red" | "green" | "blue"; type RGB = [red: number, green: number, blue: number]; const palette = { red: [255, 0, 0], green: "#00ff00", blue: [0, 0, 255] } satisfies Record<Colors, string | RGB>; // We can still access specific methods because type information wasn't lost (widened) const redComponent = palette.red.at(0); // OK (array method) const greenNormalized = palette.green.toUpperCase(); // OK (string method)
Creating types that are structurally the same but treated as different by the compiler.
type Brand<K, T> = K & { __brand: T }; type USD = Brand<number, "USD">; type EUR = Brand<number, "EUR">; const usd = 10 as USD; const eur = 10 as EUR; function tax(amount: USD): USD { return (amount * 1.1) as USD; } // tax(eur); // Error: Argument of type 'EUR' is not assignable to parameter of type 'USD'.
The new standard implementation for decorators.
function logged(originalMethod: any, context: ClassMethodDecoratorContext) { const methodName = String(context.name); function replacementMethod(this: any, ...args: any[]) { console.log(`LOG: Entering method '${methodName}'.`); const result = originalMethod.call(this, ...args); console.log(`LOG: Exiting method '${methodName}'.`); return result; } return replacementMethod; } class Person { constructor(private name: string) {} @logged greet() { console.log(`Hello, my name is ${this.name}.`); } } const p = new Person("Ron"); p.greet(); // Output: // LOG: Entering method 'greet'. // Hello, my name is Ron. // LOG: Exiting method 'greet'.
Common compiler options for modern projects.
{ "compilerOptions": { /* Base Options */ "target": "ES2022", /* Set the JavaScript language version for emitted JavaScript. */ "module": "NodeNext", /* Specify what module code is generated. */ "moduleResolution": "NodeNext", /* Specify how TypeScript looks up a file from a given module specifier. */ "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. */ "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ /* Strictness */ "strict": true, /* Enable all strict type-checking options. */ "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ /* Transpilation */ "sourceMap": true, /* Create source map files for emitted JavaScript files. */ "outDir": "./dist", /* Specify an output folder for all emitted files. */ "rootDir": "./src", /* Specify the root folder within your source files. */ /* Libraries */ "lib": ["ES2022", "DOM", "DOM.Iterable"] /* Specify a set of bundled library declaration files that describe the target runtime environment. */ }, "include": ["src/**/*"], "exclude": ["node_modules", "**/*.spec.ts"] }
Master JavaScript Arrays with this practical guide. Learn how to transform, filter, group, and process data efficiently through real-world examples, from basic operations to the latest features.
Comprehensive guide to React with practical examples, hooks, and best practices. Includes latest features from React 18 and 19.

Get instant AI-powered summaries of YouTube videos and websites. Save time while enhancing your learning experience.