Fix TypeScript build errors
TypeScript build errors usually trace to one of a few causes: misconfigured module resolution, duplicate or mismatched @types packages, a strict-flag change, or a genuine type mismatch. Diagnose with `tsc --noEmit` before changing config.
Last verified · Updated May 22, 2026
A TypeScript build error almost always traces to one of four causes: module resolution that does not match how you bundle, duplicate or mismatched @types packages, fallout from a strict-flag change, or a genuine type mismatch. Reproduce with `tsc --noEmit` and fix the cause — do not paper over it with `any` or // @ts-ignore.
Symptoms
- Build or CI fails with errors like TS2307, TS2345, or TS2322.
- Editor (tsserver) and command-line `tsc` disagree about errors.
- Errors appear only after a TypeScript or @types upgrade.
- Imports resolve at runtime but TypeScript reports 'Cannot find module'.
Likely causes
- moduleResolution does not match the bundler (node vs node16 vs bundler).
- Duplicate @types/* packages resolving to conflicting versions.
- A newly enabled strict flag (strictNullChecks, noImplicitAny) surfacing latent bugs.
- Missing type declarations for an untyped dependency.
- isolatedModules requirements not met (e.g. re-exporting a type without `export type`).
Diagnostic commands
# Reproduce the exact errors the build sees, without emitting$ npx tsc --noEmit# Print the fully-resolved config tsc is actually using$ npx tsc --showConfig# Find duplicate / mismatched type packages$ npm ls typescript$ npm why @types/node$ npm ls @types/reactCommon error patterns
| Code | Meaning | Typical fix |
|---|---|---|
| TS2307 | Cannot find module 'x' or its type declarations | Install @types/x, add a declarations.d.ts, or fix moduleResolution |
| TS2345 | Argument of type A is not assignable to parameter of type B | Correct the call site or widen/narrow the parameter type — not a cast |
| TS2322 | Type A is not assignable to type B | Fix the assignment or the declared type; check strictNullChecks fallout |
| TS2305 | Module has no exported member 'x' | Check the import name or a version mismatch in @types |
| TS1259 / TS2614 | esModuleInterop / import-shape mismatch | Enable esModuleInterop or switch to a named import |
skipLibCheck: true skips type-checking of declaration files, including your dependencies'. It is a reasonable default for speed, but if errors vanish only because skipLibCheck is on, a duplicate or mismatched @types package is the real problem — fix that rather than relying on the skip.
If your editor reports different errors than tsc, the editor is probably using a bundled TypeScript while the CLI uses the workspace version. Point the editor at the workspace TypeScript and re-run tsc --noEmit as the source of truth.
My TypeScript build fails. Here is the full output of `npx tsc --noEmit` and `npx tsc --showConfig`: <paste>. For each distinct error code, identify the root cause (module resolution, duplicate @types, strict-flag fallout, missing declarations, or a real type mismatch). Propose the smallest correct fix per group, preferring accurate types over `any` or // @ts-ignore. Flag any error that points to a duplicate @types package and tell me which `npm why` to run.
Safety: Do not suggest blanket `any`, // @ts-ignore, or disabling strict flags to make the build pass. Each fix must address the underlying cause.
Safe fix workflow
- Reproduce with `npx tsc --noEmit` so you fix what the build sees, not the editor.
- Group errors by TS code and fix one group at a time.
- For TS2307, decide whether it is a missing @types package, a missing declarations.d.ts, or a moduleResolution mismatch.
- For TS2345/TS2322, fix the type at the source rather than casting; re-run tsc.
- Run `npm why` on any type package that appears in two versions and dedupe.
- Re-run `tsc --noEmit` after each group and confirm the error count drops.
Test plan
- `npx tsc --noEmit` passes with zero errors
- Unit and integration tests pass on the fixed build
- Production build (`npm run build`) succeeds
- No new // @ts-ignore or `any` was introduced to silence an error
- Editor and CLI report the same result after pointing the editor at the workspace TS
Escalation checklist
- An error persists only because skipLibCheck is on
- A dependency ships broken or duplicated .d.ts files you cannot dedupe
- An error reproduces on one Node/moduleResolution combination only
- A strict-flag change reveals a latent runtime bug needing a code fix, not a type fix
Related upgrade pages
Official sources
Backs the breaking-change and migration-step claims.
Backs the breaking-change and migration-step claims.
Copy-ready AI prompts
Structured prompts for an AI coding assistant. Inspect first, then execute incrementally, and keep a human in the review loop.
You are helping with a TypeScript migration: diagnose and fix TypeScript build errors. Do not edit files yet. First inspect the repository and report: 1. The exact typescript version in package.json and the lockfile, plus every @types/* package and whether duplicates resolve to different versions (run `npm ls typescript` and `npm why @types/node`). 2. The active tsconfig.json options: strict flags, moduleResolution, target/module, experimentalDecorators, isolatedModules, skipLibCheck, and any removed-in-5.0 flags (--out, --target ES3, --keyofStringsOnly, --charset, --noImplicitUseStrict). 3. Files using decorators and whether they rely on the legacy (experimentalDecorators) model. 4. The build/typecheck command and whether the project emits with tsc or a bundler. 5. Any // @ts-ignore / // @ts-expect-error suppressions and any JS files type-checked via allowJs/checkJs. Return: a risk summary, the highest-risk files, a suggested migration order, the commands to run before editing, and any questions that need human confirmation.
Safety: Inspection only. The agent must not modify files in this step.
Works with Claude Code, Cursor, GitHub Copilot
Triage this failing TypeScript build. Input: the full `tsc --noEmit` output and `tsc --showConfig`. Group errors by code (TS2307, TS2345, TS2322, TS2305, TS1259), explain the root cause of each group, and propose the smallest correct fix — accurate types over casts. Call out any error caused by a duplicate @types package and the `npm why` command to confirm it.
Safety: No blanket any, // @ts-ignore, or strict-flag disabling. Every fix addresses the underlying cause.
Works with Claude Code, Cursor, GitHub Copilot
Test plan
Commands
npx tsc --noEmitnpx tsc --showConfignpm run buildnpm test -- --watch=false
Manual checks
- Confirm editor (tsserver) and CLI tsc agree after pointing the editor at the workspace TypeScript.
- Verify that imports flagged TS2307 actually resolve at runtime.
- Re-check any error that only disappears with skipLibCheck enabled.
Regression risks
- Casts or `any` introduced under deadline that hide real type bugs.
- skipLibCheck masking a duplicate @types mismatch.
- moduleResolution change breaking runtime resolution for some dependencies.
Acceptance criteria
- `tsc --noEmit` exits clean with zero errors.
- Build and tests pass with no new suppressions.
- All @types/* packages resolve to a single version.
Frequently asked questions
Why does my editor show errors that `tsc` doesn't (or vice versa)?
Almost always a TypeScript version mismatch: the editor uses its bundled compiler while the CLI uses the workspace version. Point the editor at the workspace TypeScript and treat tsc --noEmit as the source of truth.
Is it ever okay to use skipLibCheck or // @ts-ignore?
skipLibCheck is a fine speed optimization, but if it is the only thing hiding an error you have a duplicate/mismatched @types package to fix. Prefer // @ts-expect-error over // @ts-ignore so suppressions self-clean, and never use either to mask a real type bug.