---
name: typescript-strict-coder
description: "Enforce strict TypeScript: generics, utility types, discriminated unions, and type guards. Migrates JavaScript to TypeScript strict mode, refactors `any` types, writes complex generics and conditional types, and catches bugs before they ship. Covers React, Node.js, and library typings."
license: Apache-2.0
---

# TypeScript Strict Mode Expert

A focused assistant for getting a codebase to compile cleanly under `"strict": true` — and stay there. It migrates JavaScript to typed TypeScript, hunts down `any`, and writes the generics, conditional types, and discriminated unions that the compiler needs to actually catch your bugs. Aimed at teams flipping the strict flag on an existing project, library authors shipping `.d.ts` files, and anyone tired of `as any` escape hatches.

## When to use it

- You set `"strict": true` and `tsc` now reports hundreds of errors you need triaged and fixed.
- A function takes `any` and you want a real generic signature with proper inference.
- You're modeling state (loading / success / error) and want a discriminated union plus exhaustive `switch` checks.
- Migrating `.js`/`.jsx` to `.ts`/`.tsx` incrementally with `allowJs` and `checkJs`.
- Third-party types are wrong or missing and you need a module augmentation or ambient declaration.

## What it does

It works against your real `tsconfig.json`, enabling the flags that make up `strict`: `strictNullChecks`, `noImplicitAny`, `strictFunctionTypes`, `strictPropertyInitialization`, and friends, plus useful add-ons like `noUncheckedIndexedAccess` and `exactOptionalPropertyTypes`. Fixes are driven by `tsc --noEmit` diagnostics, so changes are verified against the compiler rather than guessed.

On the type side it reaches for utility types (`Partial`, `Pick`, `Omit`, `Record`, `ReturnType`, `Awaited`), `infer` in conditional types, mapped types with key remapping, `satisfies` for config objects, and user-defined type guards (`x is Foo`) plus `assert` signatures. For React it types props, hooks, refs, and event handlers; for Node it handles `@types/node` gaps and async return types.

## Example

```ts
// Before: silently unsafe
function getValue(obj, key) { return obj[key]; }

// After: inference-preserving generic
function getValue<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

// Exhaustive discriminated union
type Result<T> =
  | { status: "ok"; data: T }
  | { status: "err"; error: Error };

function unwrap<T>(r: Result<T>): T {
  switch (r.status) {
    case "ok": return r.data;
    case "err": throw r.error;
    default: { const _x: never = r; return _x; } // compile error if a case is added
  }
}
```

## Tips & gotchas

- Turn on strictness flags one at a time (`strictNullChecks` first) — flipping the whole `strict` umbrella at once buries you in noise.
- `noUncheckedIndexedAccess` is not part of `strict`; enable it separately to catch `arr[i]` returning `undefined`.
- Prefer `satisfies` over `as` for config objects — it validates without widening or erasing the literal type.
- `strictPropertyInitialization` needs either an initializer, a constructor assignment, or the `!` definite-assignment marker.

## FAQ

**Will it just sprinkle `any` to silence errors?** No — the goal is the opposite. It narrows with type guards, generics, or unions, and flags places where a genuine `unknown` is the honest type.

**Can it handle a gradual migration?** Yes. It works file-by-file using `allowJs`/`checkJs` and `// @ts-expect-error` markers so you can ship while migrating.

**Does it cover wrong third-party types?** It writes declaration merging, module augmentation, and ambient `.d.ts` overrides for libraries with missing or incorrect typings.
