← All decisions

TypeScript strict mode everywhere, no exceptions

accepted

0007 — TypeScript strict mode everywhere, no exceptions

Context

For a multi-tenant system, the cost of “I forgot to scope this by org_id” is data leakage between organizations. The cost of an any somewhere is exactly that — the type system can’t catch the bug, and the test suite has to be perfect to compensate.

Combined with TDD posture (ADR 0009), strict TypeScript is the second leg of the stability stool.

Decision

Every package and app uses tsconfig.base.json which sets strict: true, noUncheckedIndexedAccess: true, noImplicitOverride: true, noFallthroughCasesInSwitch: true, exactOptionalPropertyTypes: true. No any without a // @ts-expect-error: <reason> or a written justification in a comment. No // @ts-nocheck ever.

Zod schemas at every external boundary (HTTP requests, DB rows, env vars, config files). The Zod schema is the source of truth; TS types are derived via z.infer<>.

Consequences

Easier:

Harder:

Trip-wires

If a single any slips in, the reviewer (human or AI) flags it and writes the explicit comment or replaces with a real type. We don’t tolerate accumulating type debt — at this size, every escape valve is a foothold for future bugs.

Alternatives considered