skipLibCheck

Skips type checking of all .d.ts files, trading accuracy for build speed.

Signature
"skipLibCheck": boolean
  • Added in TypeScript 2.0

Parameters

ParameterTypeDescription
$trueoptionalbooleanSkips type checking of every .d.ts file in the program, including TypeScript's own bundled lib files and everything under node_modules/@types.
$falseoptionalbooleanDefault. Every declaration file reachable from your program is fully type checked.

Return value

Suppresses type errors reported inside declaration files, including the bundled lib files.

Errors

Nothing. It only suppresses errors; syntax errors in a .d.ts file are still reported, and declarations are still read and used for checking your own code.

Changelog

  • PHP 4.5Bundled lib files can be replaced by npm packages such as @typescript/lib-dom, which is often a more precise fix than skipping checks entirely.
  • PHP 6.0libReplacement now defaults to false for performance, so lib overrides must be opted into explicitly.

skipLibCheck stops TypeScript from type checking declaration files. Your own source is still fully checked, and the declarations are still read — they just are not verified against each other.

What it is really for

The classic case is two copies of a library's types in node_modules: a transitive dependency pins @types/react@17 while you use 18, and every render suddenly reports duplicate or incompatible identifiers in files you did not write and cannot edit. The second case is a TypeScript upgrade that tightens a rule and lights up declarations across your dependency tree, when you only wanted to bump a compiler version.

The trade

You gain build time and quiet, and you lose accuracy. If two libraries declare the same type in inconsistent ways, that inconsistency now passes silently and can produce nonsense inference in your code — you simply do not hear about it. The errors were often real.

Better fixes first

Prefer deduplicating the offending package (npm overrides, yarn resolutions, pnpm overrides) so only one copy of the types exists. If the problem is in TypeScript's own standard library, replace just that file with a lib-replacement package rather than switching off checking everywhere.

Example

Example · typescript
// tsconfig.json
//   { "compilerOptions": { "skipLibCheck": true } }
//
// node_modules holds two copies of @types/react. Without the flag:
//   node_modules/@types/react/index.d.ts(3021,14): error TS2300:
//     Duplicate identifier 'LibraryManagedAttributes'.
// With it, those errors disappear — your own code is still checked.

interface Money { cents: number }

const price: Money = { cents: 1999 };
// const bad: Money = { cents: "1999" };  // still error TS2322 — your code is checked

console.log(price.cents);
// -> 1999

When to use it

  • Unblocking a build when two versions of @types/react are installed at once.
  • Upgrading TypeScript without first fixing every newly reported error in node_modules.
  • Cutting compile time on a project with a very large dependency tree.
  • Working around a dependency that ships a declaration file with a real type error.

Frequently asked questions

Is it safe to enable skipLibCheck?

It is safe in the sense that it never changes emitted code, but it does lower type-system accuracy by hiding genuine conflicts between declaration files. Prefer deduplicating conflicting @types packages with npm overrides or yarn resolutions, and use the flag when that is not possible.

Does skipLibCheck stop checking my own code?

No, only .d.ts files are skipped, including TypeScript's bundled lib files. Every .ts and .tsx file you write is still fully type checked.

Why do I get errors inside node_modules that I cannot fix?

Usually because two versions of a library's types are installed and their declarations clash, or a TypeScript upgrade tightened a rule those declarations violate. Pin a single version of the @types package first; skipLibCheck is the fallback when the dependency tree cannot be flattened.

More examples

Deduplicate before you skip

Almost every skipLibCheck story starts as a duplicate-types story, and pinning a single version fixes the cause rather than muting the symptom. Reach for the flag only when the duplication genuinely cannot be resolved.

Example · typescript
// package.json — the fix that keeps type safety:
// {
//   "overrides":    { "@types/react": "18.3.12" },   // npm
//   "resolutions":  { "@types/react": "18.3.12" }    // yarn / pnpm
// }
//
// One copy of the types in node_modules means no duplicate-identifier
// errors, and no need to stop checking declaration files at all.

import type { ReactNode } from "react";

const render = (children: ReactNode): string =>
  Array.isArray(children) ? `${children.length} nodes` : "1 node";

console.log(render(["a", "b", "c"]));
// -> 3 nodes

What it does not protect you from

The flag suppresses errors located in declaration files, not the influence those declarations have on inference. A .d.ts that lies about a return type is just as harmful either way, so skipping the check buys speed and quiet, never correctness.

Example · typescript
// A dependency ships a wrong declaration:
//   // node_modules/tiny-lib/index.d.ts
//   export declare function parseAge(input: string): string;   // actually returns number

import { parseAge } from "tiny-lib";

const age = parseAge("42");    // typed string, whatever skipLibCheck is set to
console.log(age.toUpperCase()); // compiles; throws at runtime
// -> TypeError: age.toUpperCase is not a function

// skipLibCheck hides errors INSIDE .d.ts files.
// It does not stop those files from describing your code incorrectly.

Discussion

  • Be the first to comment on this lesson.