Typescript Strict
by @clawkk
Deep TypeScript strictness workflow—incremental enablement, compiler flags, typing boundaries, narrowing, generics, utility types, and safe refactors. Use wh...
clawhub install typescript-strict📖 About This Skill
name: typescript-strict description: Deep TypeScript strictness workflow—incremental enablement, compiler flags, typing boundaries, narrowing, generics, utility types, and safe refactors. Use when adopting strict mode, reducing any, or hardening large TS codebases.
TypeScript Strict Mode (Deep Workflow)
Strictness is a gradient, not a single switch. The goal is fewer runtime surprises without blocking delivery—via incremental migration and clear typing boundaries at IO edges.
When to Offer This Workflow
Trigger conditions:
strict, strictNullChecks, noImplicitAny, or noUncheckedIndexedAccessany and @ts-ignore.d.ts exportsInitial offer:
Use six stages: (1) baseline & goals, (2) compiler flags roadmap, (3) boundary typing, (4) narrowing & exhaustiveness, (5) generics & patterns, (6) verify & guardrails). Confirm TS version, build tool (tsc, esbuild, etc.), and monorepo layout.
Stage 1: Baseline & Goals
Goal: Know current pain and target strictness with metrics.
Actions
tsc --noEmit error count and top files by errorsExit condition: Baseline error count + priority directories.
Stage 2: Compiler Flags Roadmap
Goal: Enable flags incrementally—fix clusters, not the whole repo at once.
Typical order (adapt)
1. strictNullChecks (often highest value)
2. noImplicitAny on new files + ratchet old
3. strictFunctionTypes, strictBindCallApply
4. noUncheckedIndexedAccess (verbose—plan for undefined unions)
5. exactOptionalPropertyTypes (sharp edges—later)
Techniques
// @ts-expect-error with ticket over blind @ts-ignoretsconfig extends for stricter packagesany in changed lines (eslint @typescript-eslint/no-explicit-any)Exit condition: Flag timeline with owners per package.
Stage 3: Boundary Typing (IO Edges)
Goal: Validate external data once; internal code trusts narrowed types.
Patterns
zod / io-ts / valibot for runtime parse at API boundarysatisfies for config objects—keeps literal typesunknown without validationAPIs
type UserId = string & { __brand: 'UserId' }) to prevent mix-upsExit condition: New IO code has parse → typed pipeline documented.
Stage 4: Narrowing & Exhaustiveness
Goal: Control flow analysis works for you—discriminated unions, never checks.
Practices
{ status: 'loading' } | { status: 'ok', data: T }switch with assertNever(x) for compile-time exhaustivenessNullability
undefined vs null one convention per codebase sectionExit condition: Representative modules refactored with fewer optional footguns.
Stage 5: Generics & Patterns
Goal: Reuse without any soup—constraints and defaults.
Guidance
extends constraints; avoid unconstrained generics unless truly genericReturnType / Parameters for inference gluePerformance
tsc—split types or simplifyExit condition: Style guide section for generics in shared libraries.
Stage 6: Verify & Guardrails
Goal: Strictness sticks—regressions caught in CI.
CI
tsc --noEmit required green for affected projectsdtslint or tsd for library typings tests when authoring packagesRefactor safety
Final Review Checklist
Tips for Effective Guidance
unknown over any—forces narrowing at use site.noUncheckedIndexedAccess, show helper getters or Record patterns.Handling Deviations
d.ts or wrapper module with narrow exports.