TypeScript
TypeScript code style conventions
TypeScript code style + formatting.
MUST
- Arrow functions only. Why: one function form.
- All exports in a single block at end of file. Why: lint-enforced, scan-once.
.tsxsingle component →export default; utilities/backend → named exports. Why: convention.- ANY file with JSX uses
.tsx— even a context provider<Ctx value={...}>. Why: biome parses.tsas non-JSX, misreads<Foo>as comparison/regex, fixer infinite-loops (90-min hang). forloops overreduce()/forEach(). Why: readability + perf.- Exhaustive
switchwithdefault: never. Why: compile-time case coverage. - Descriptive
catch (error)state-var names (chatError,formError). Why: oxlint shadow rule. - Short map callback names (
t,m,i). Why: convention. - Destructured object for 4+ args (max 3 positional). Why: call-site clarity.
- Co-locate components with their page; move to
~/componentsonly when reused. Why: locality. - Explicit imports from exact file paths; no barrel
index.tsin app code (library packages use barrels for public API). Why: avoids barrel cycle + bloat. - Prefer existing libraries over new dependencies. Why: minimize surface.
node:prefix for Node builtins (import { join } from 'node:path'). Why: explicit builtin.interfaceovertypewhere possible; properties sorted alphabetically. Why: lint-enforced.import typefor type-only imports. Why: erased at build.
NEVER
functiondeclarations. Cost: violates arrow-only.- Duplicate types. Cost: drift; single source of truth.
import asaliases. Cost: rename the variable instead.- Empty lines between statements. Cost: biome deletes them — wasted diff.
- Trailing comma single-line (keep it multi-line). Cost: format violation.
Formatting
- Single quotes, no semicolons; imports sorted alphabetically by source.