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 π β
- Code MUST be formatted with Prettier. Editors MUST format on save.
Note: Prettier is used by Google's gts. Biome is a rising 2026 alternative; Prettier remains the default.
2. Type Safety π β
tsconfigMUST enablestrict. ImplicitanyMUST NOT be used.typealiases and discriminated unions SHOULD be preferred overclasshierarchies (Β§5).- A Brand Type MUST be used to give Nominal Typing where two structurally identical types must not be interchangeable (e.g.
UserIdvsOrderId).
3. Immutability π β
- Variables MUST be declared
const.letMAY be used only where reassignment is required.varMUST NOT be used. - Data types MUST be deeply
readonly(readonlymembers,ReadonlyArray<T>,Readonly<T>,as constfor literals). A mutable type MUST be used only where in-place mutation is intended. - Function parameters MUST NOT be mutated; spread SHOULD be preferred over
Object.assign. - Immutability MUST be enforced by
eslint-plugin-functional.
Rationale: const prevents rebinding only, not content mutation. Deep readonly is stricter than Google/Airbnb.
4. Total Types π β
- Project code MUST NOT use
undefinedin its own types. - Domain and application types MUST NOT signal absence with
undefinedor a barenullβ use Option (Maybe). Optional properties (x?: T) andT | undefinedunions MUST NOT mean "maybe absent." - Functions MUST return
TorOption<T>, neverT | undefined. nullMAY appear at the boundary (DB rows, JSON, the DOM,Map.get, third-party APIs). It MUST be converted toOption<T>in the adapter before entering the pure core.tsconfigMUST enablestrictNullChecksandnoUncheckedIndexedAccess.
β "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 π β
classMUST NOT be used in project code; prefer functions, plain data, and closures.- Classes MAY be used where a framework or library requires them.
β 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 π β
Failures MUST be modeled as a Result (Either):
tstype Result<T, E> = | { ok: true; value: T } | { ok: false; error: E[] };The
Resultunion SHOULD be hand-rolled (KISS / YAGNI).neverthrowMAY be adopted only where its combinators (map/andThen/mapErr/ResultAsync) are needed at scale.IO /
fetch/ DB calls MUST be wrapped at the boundary and return aResult; the pure core MUST stay free oftry/catch.
β 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 β
- Google TypeScript Style Guide β https://google.github.io/styleguide/tsguide.html
- TypeScript Handbook, Classes β https://www.typescriptlang.org/docs/handbook/2/classes.html
tsconfigstrictreference β https://www.typescriptlang.org/tsconfig/strict.html- Airbnb JavaScript Style Guide β https://github.com/airbnb/javascript
- Google
gtsβ https://github.com/google/gts eslint-plugin-functionalβ https://github.com/eslint-functional/eslint-plugin-functional- Biome β https://biomejs.dev/