Typescript Golden Rules
Important rules to remember using typescript strict**.
THE 10 GOLDEN RULES
Memorize these. Ship by them. Never break them.
1 Strict Mode Always On tsconfig.json must have ‘strict: true’. This enables strictNullChecks, noImplicitAny, strictFunctionTypes, and more. If it’s not strict, it’s not TypeScript — it’s JavaScript with extra steps.
2 Never Use ‘any’ Every ‘any’ is a lie. It tells the compiler to stop checking. Use ‘unknown’ when you genuinely don’t know the shape, then narrow it. Use proper types everywhere else. If an AI agent adds ‘any’, replace it.
3 Define Types for Everything Every prop, every API response, every Supabase row gets an explicit type or interface. No inline object shapes in JSX. If you define it twice, extract it to a shared types file.
4 Use Zod for All Input Validation
TypeScript types exist at compile time. At runtime — API routes, form data, webhooks —
you have no guarantees. Zod validates the shape at runtime AND infers the TypeScript
type. Use z.infer
5 Never Skip Return Types on Functions Always declare the return type of functions, especially async ones. Promise<UserRow | null> tells you and every caller exactly what to expect. Inferred return types are fine inside components, not on shared utilities.
6 Narrow Before You Access Never access a property on a value that could be null or undefined without checking first. Use if-checks, optional chaining (?.), or nullish coalescing (??) — but never the non-null assertion operator (!) unless you have absolute certainty and a comment explaining why.
7 Use discriminated unions for state Represent async states as discriminated unions, not multiple booleans. { status: ‘idle’ | ‘loading’ | ‘success’ | ‘error’ } is always safer than isLoading + isError + isSuccess. One field, no impossible combinations.
8 Keep Types Co-Located or Centralized Types used in one file live in that file. Types shared across 2+ files live in lib/types/ or a domain-specific types.ts. Never scatter the same type definition across multiple files — that’s how drift happens.
9 Type Your Supabase Queries Run ‘supabase gen types typescript’ to regenerate types after schema changes. Use the generated Database type for all queries. Never assert Supabase responses as ‘any’ — the generated types tell you exactly what comes back.
10 Run the Full Check Before Committing npx tsc –noEmit catches type errors without building. Run it before every commit. If CI catches a type error you didn’t, that’s a broken workflow — add tsc to your pre-commit hook or gate check and fix it locally first.
Boots On The Ground Ai | bootsagentai.com Page 4 CONFIDENTIA