Turn on skipLibCheck
· Last updated · 4 min read · #javascript #typescript

Turn on skipLibCheck. TypeScript’s own tsc --init already does.
I used to treat it like a guilty secret: a speed hack you enable on your laptop and switch off in CI, so the “real” typecheck still runs somewhere.
Please don’t do that.
The flag doesn’t make TypeScript sloppy about your code. It stops TypeScript type-checking declaration files, and most of those live in node_modules, where you can’t fix them anyway. Failing CI on them isn’t extra safety. It’s extra waiting.
What is skipLibCheck?
skipLibCheck (opens in a new tab) tells tsc to skip type-checking .d.ts files.
{
"compilerOptions": {
"skipLibCheck": true
}
}
The compiler’s default is still false, while the recommended config says true. That gap is why this flag keeps coming up in blog posts like this one.
TypeScript still reads those .d.ts files, and still uses them to check your imports, power your autocomplete and report your errors. What it stops doing is walking through each declaration file looking for problems inside the library itself.
The 2.0 release notes (opens in a new tab) explain the motivation: when a program includes large declaration files, the compiler spends a lot of time checking declarations that are already known to be error-free.
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 function wrong and you still get an error. Pass a string where the .d.ts says number, and TypeScript still complains.
What you give up is TypeScript auditing the internals of those .d.ts files. That includes TypeScript’s own lib.d.ts and the DOM types, not just node_modules.
The failures it swallows look like this: two slightly different copies of the same type in node_modules, a library built against an older TypeScript than yours, or a DefinitelyTyped package whose own declarations don’t type-check.
The official docs are honest about the trade. You give up a little type-system accuracy in exchange for time, and TypeScript checks the code you actually use instead of every .d.ts it happened to load. That’s the trade you want, because the errors inside node_modules are almost never yours to fix.
The name is a little wrong
“Lib” makes you think of lib.d.ts and node_modules, but the flag skips every .d.ts file, including yours.
If you keep a pile of ambient src/types/*.d.ts files, TypeScript won’t check those files for internal consistency. It’ll still use their types when it checks your .ts code.
If that bothers you, move the types into a .ts module and import them. Then they’re source code, and they get checked like source code.
That’s the real catch with this flag, and it has nothing to do with “maybe I should turn it off in production.”
Should I turn it off in CI?
No.
I’ve seen teams split it: skipLibCheck: true on laptops and false on the build server, on the theory that CI has time to be thorough.
Then CI fails because some-library/index.d.ts has two conflicting copies of Request, or because you bumped TypeScript and a transitive @types package didn’t keep up. You didn’t ship a bug. You just lost a weekend.
Errors inside those files are usually unactionable, because they point at upstream packages. Most projects end up turning the flag on sooner or later for exactly this reason.
If two copies of a library’s types really are fighting in your dependency tree, skipLibCheck is a bandage. The actual fix is getting back to one copy of the dependency, with your package manager’s resolutions or by working out why the tree forked. The docs recommend that too.
Keep the flag on while you fix it, and keep it on afterwards.
Does a faster compiler make this obsolete?
TypeScript 7 is a native compiler, and full builds on large repos are often around 8 to 12 times faster than on TypeScript 6. A lot of tooling still sits on 6 for now, because 7.0 didn’t ship a stable programmatic API.
Either way, leave skipLibCheck on. Speed was never the only reason for it. Type-checking other people’s declaration files just isn’t a useful job, and a faster compiler only does that useless job faster.
What’s the catch?
There are two, and both are small.
Your own .d.ts files go unchecked. Covered above: if you write ambient declarations, skipLibCheck won’t proofread them for you.
Some errors only appear when a .d.ts is checked. The 2.0 notes give the example of a .ts file augmenting a type declared in a .d.ts file, where the inconsistency is only reported when the declaration file gets checked. They also say this is rare in practice, and I’ve never hit it.
What you shouldn’t do is treat skipLibCheck as optional seasoning. It’s a sensible 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