TypeScript Style Guide

Per-language style guide for TypeScript. Shared rules: the Coding Style Guide. Requirement levels follow RFC 2119; tags 🌎 / 🏠 are defined there.

1. Formatting 🌎

Note: Prettier is used by Google's gts. Biome is a rising 2026 alternative; Prettier remains the default.

2. Type Safety 🌎

3. Immutability 🏠

Rationale: const prevents rebinding only, not content mutation. Deep readonly is stricter than Google/Airbnb.

4. Total Types 🏠

❌ "Maybe absent" leaks out of the function as undefined:

function findUser(id: UserId): User | undefined {
  return users.get(id); // callers must remember to check
}

βœ… Absence is explicit in the type:

import { type Option, some, none } from "./option";

function findUser(id: UserId): Option<User> {
  const user = users.get(id);
  return user === undefined ? none : some(user);
}

Rationale: null is a defined value and the DB-native representation of absence; undefined is accidental "not set." Divergent from Google, which treats undefined as normal; not a language-wide ban.

5. Classes 🏠

❌ State and behavior bundled in a class:

class Rectangle {
  constructor(private readonly w: number, private readonly h: number) {}
  area(): number {
    return this.w * this.h;
  }
}

βœ… Plain data plus a function:

type Rectangle = { readonly w: number; readonly h: number };

const area = (r: Rectangle): number => r.w * r.h;

Rationale: divergent from mainstream β€” classes are first-class in TypeScript; Google discourages only static-only namespacing classes.

6. Error Handling 🏠

❌ Failure is thrown, and a caller can ignore it:

async function loadUser(id: UserId): Promise<User> {
  const res = await fetch(`/users/${id}`);
  if (!res.ok) throw new Error("request failed");
  return res.json();
}

βœ… Failure is returned as a Result the caller must handle:

async function loadUser(id: UserId): Promise<Result<User, string>> {
  try {
    const res = await fetch(`/users/${id}`);
    if (!res.ok) return { ok: false, error: ["request failed"] };
    return { ok: true, value: await res.json() };
  } catch {
    return { ok: false, error: ["network error"] };
  }
}

Rationale: divergent from Google's TS guide, which prefers throwing exceptions.

References