Skip to main content
Zubin Khavarian
Watercolor of a person writing in a small notebook at a lamp-lit desk, with a tall ignored wall of dusty library ledgers behind them.

Turn on skipLibCheck

· Last updated

Turn on skipLibCheck. TypeScript’s own tsc --init already does.

I used to treat it like a guilty secret. A speed hack you enable locally and turn off in CI, so the “real” typecheck still runs.

Don’t do this.

The flag does not make TypeScript sloppy about your code. It stops TypeScript from type-checking declaration files. Most of those files are in node_modules. You cannot fix them. Failing CI on them is not extra safety. It is extra waiting.

What is skipLibCheck?

skipLibCheck 🔗 tells tsc to skip type-checking .d.ts files.

{
  "compilerOptions": {
    "skipLibCheck": true
  }
}

The compiler default is still false. The recommended config is true. That gap is why this flag keeps showing up in blog posts.

TypeScript still reads those .d.ts files. It still uses them to check your imports, your autocomplete, your errors. It does not walk each declaration file looking for problems inside the library.

The 2.0 release notes 🔗 put it this way: when a program includes large declaration files, the compiler spends a lot of time checking declarations that are already known not to contain errors.

Your code is still checked

This is the bit the name gets wrong.

skipLibCheck does not skip your .ts and .tsx files. Call a library wrong and you still get an error. Pass a string where the .d.ts says number, and TypeScript still complains.

What you lose is TypeScript auditing the internals of those .d.ts files. That includes TypeScript’s own lib.d.ts and the DOM lib, not only node_modules.

Two copies of the same type in node_modules, each slightly different. A library shipped against an older TypeScript than yours. A DefinitelyTyped package whose own .d.ts does not type-check. Those are the failures this flag swallows.

The official docs are honest about the cost. You trade some type-system accuracy for time. TypeScript checks the code you actually refer to in your source, instead of doing a full check of every .d.ts it loaded.

That is the trade you want. The errors inside node_modules are almost never yours to fix.

The name is a little wrong

“Lib” sounds like lib.d.ts and node_modules. The flag skips all .d.ts files. Yours too.

If you keep a pile of ambient src/types/*.d.ts files, TypeScript will not type-check those files for internal consistency. It will still use the types from them when checking your .ts.

If that bothers you, put the types in a .ts module and import them. Then they are source, and they get checked.

This is the real catch. Not “maybe I should disable it in production.”

Should I turn it off in CI?

No.

I have seen teams do the split. skipLibCheck: true on the laptop, false on the build server. The idea is that CI has time to be thorough.

CI then fails because some-library/index.d.ts has two conflicting copies of Request, or because you bumped TypeScript and a transitive @types package did not. You did not ship a bug. You lost a weekend.

Errors inside those files are typically unactionable. They point at upstream packages. Most projects end up with the flag on for one reason or another.

If two copies of a library’s types are fighting in your tree, skipLibCheck is a bandage. The fix is still one copy of the dependency. Use your package manager’s resolutions, or figure out why the tree forked. The docs recommend that too.

Leave the flag on while you do it. Leave it on after.

Does a faster compiler make this obsolete?

TypeScript 7 is a native compiler. Full builds on large repos are often around 8x to 12x faster than TypeScript 6. A lot of tooling still sits on 6, because 7.0 did not ship a stable programmatic API.

Either way, leave skipLibCheck on.

Speed was never the only reason. The other reason is that type-checking other people’s declaration files is not a useful job. A faster compiler does that useless job faster. It does not make the job useful.

What’s the catch?

Two, and they are both small.

Your own .d.ts files go unchecked. Covered above. If you author ambient declarations, know that skipLibCheck will not proofread them.

Some errors only show up when the .d.ts is checked. The 2.0 notes give the example: a .ts file augments a type that was declared in a .d.ts file. The inconsistency might only be reported when that declaration file is checked. They also say this is rare in practice. I have never hit it.

What you should not do is treat skipLibCheck as optional seasoning. It is a default. Turn it on, keep it on, and spend the time you get back on your own types.

Stay in touch

Don't miss out on new posts or project updates. Hit me up on X for updates, queries, or some good ol' tech talk.

Follow @zkMake
Zubin Khavarian, Principal Front-End EngineerWritten by