32 lines | 1.3 KB

TypeScript — Claude Code rules

tsconfig

Assume the following flags are on (and don't disable them):

  • strict: true
  • noUncheckedIndexedAccess: true
  • noImplicitOverride: true
  • noFallthroughCasesInSwitch: true
  • noUnusedLocals / noUnusedParameters: true
  • verbatimModuleSyntax: true

Type discipline

  • Never introduce any. If the type is unknown, type it as unknown and narrow.
  • Prefer union literal types over enums (type Status = "idle" | "running" | "done"). Enums emit runtime code and have surprising structural behaviour.
  • Use satisfies to keep object literals widely typed while ensuring conformance.
  • as is a last-resort escape hatch. If you need it, add a comment explaining why a narrower form isn't possible.

Patterns

  • Discriminated unions for state machines ({ kind: "loading" } | { kind: "loaded"; data: T }).
  • Result<T, E> style returns instead of throwing for expected failures.
  • Branded types (type UserId = string & { __brand: "UserId" }) for IDs that mustn't get mixed up.

Module shape

  • Each module exports types alongside the values that use them.
  • import type { … } for type-only imports (verbatimModuleSyntax enforces this).
  • Don't re-export everything from a barrel — name the surface explicitly.