Strict mode turns a category of production bugs — null references, mismatched shapes, silent `undefined` — into compile-time errors caught before a PR merges. The upfront cost is a slower first commit; the payoff is fewer 2am incidents and a codebase where refactors don't require a prayer. On a ten-year timeline, that trade is not close.
Yes — almost always incrementally, never a big-bang rewrite. We start with an `any`-audit to find where types currently lie, rename files `.js` → `.ts` package by package, and roll strict mode out file by file as coverage climbs. The build stays green the entire time.
tRPC when client and server live in the same TypeScript monorepo — it skips codegen entirely and the types are always in sync. We reach for ts-rest or a typed OpenAPI contract when the API needs to serve external consumers, mobile clients, or teams outside the monorepo who need a stable, documented REST surface.
`tsconfig.json` ships with `strict: true` plus `noUncheckedIndexedAccess` and `exactOptionalPropertyTypes` on every project we own. `any` is not banned outright — it's lint-flagged via typescript-eslint and requires an inline comment justifying why, reviewed like any other suppressed warning. In practice it appears almost exclusively at the boundary of an untyped third-party library.
Yes. When a dependency ships without types and DefinitelyTyped doesn't cover it, we write a scoped `.d.ts` shim — typing only the surface we actually call, not the whole library. That keeps the `any` boundary small, explicit, and easy to find later.
Vitest end to end — unit, integration, and type-level tests via `expectTypeOf`, all in the same runner that already understands your `tsconfig`. CI runs `tsc --noEmit` as its own gate before the test suite even starts, so a type error fails fast and never burns test-runner time.
10 — Start
Let's build something worth typing.
Two-week diagnostic, four-week MVP, twelve-week ground-up. Bring the brief — we'll send a plan, not a pitch deck.