There is a lot of confusion about the TypeScript option skipLibCheck
. From the documentation:
Skip type checking of declaration files.
This can save time during compilation at the expense of type-system accuracy. For example, two libraries could define two copies of the same
type
in an inconsistent way. Rather than doing a full check of alld.ts
files, TypeScript will type check the code you specifically refer to in your app’s source code.A common case where you might think to use
skipLibCheck
is when there are two copies of a library’s types in yournode_modules
. In these cases, you should consider using a feature like yarn’s resolutions to ensure there is only one copy of that dependency in your tree or investigate how to ensure there is only one copy by understanding the dependency resolution to fix the issue without additional tooling.Another possibility is when you are migrating between TypeScript releases and the changes cause breakages in node_modules and the JS standard libraries which you do not want to deal with during the TypeScript update.
Note, that if these issues come from the TypeScript standard library you can replace the library using TypeScript 4.5’s lib replacement technique.
So, what does this mean? There are two types of TypeScript files: Source files (.ts
, .cts
, .mts
, and .tsx
) and declaration files (.d.ts
, .d.cts
, .d.mts
, and .d.*.ts
). Normally you write source files. If you want to publish types, typically a library, you use tsc
to generate declaration files. There are valid use cases to write declaration files, but they are generally more advanced use cases.
So what’s the point of skipLibCheck
? Libraries that are published contain declaration files. Typically libraries built with tsc
are correct, but there are a lot of third party tools out there that produce incorrect results, and there are also a lot of incorrect handwritten types. Or sometimes types of different libraries may simply conflict. Enabling skipLibCheck
allows you to use their types to some extent, despite type errors.
Here’s another way to explain skipLibCheck
:
- A
// @ts-ignore
comment disables type checking for the next line. - A
// @ts-nocheck
comment is like applying a// @ts-ignore
comment an entire file. skipLibCheck
is like applying a// @ts-nocheck
comment to every declaration file.
So is it dangerous to partially disable type checking for a project? Yes. The behaviour is undefined and may change at any time. If you partially disable type checking, A type named any
may slip into your code base. However, while TypeScript displays this type as any
, or sometimes /*unresolved*/ any
, it doesn’t actually behave like a regular any
. It’s behaviour is undefined.
Should I enable skipLibCheck
? Ideally you don’t. If your project compiles without this option, leave it to false
. Maybe you accidentally pull in a problematic devDependency whose types you don’t actually need. In that case it’s best to use the types
compiler option. This may be useful to do anyway, as it can speed up type checking for your project. For example:
For libraries it’s important to know their types don’t conflict with their dependencies. For applications this is often less important. So I’m inclined to say skipLibCheck
for applications is less problematic than for libraries.
What if my framework or build tool makes me author or commit declaration files? Your framework is wrong. Please raise an issue with them.
Need more convincing? This repository contains a project with skipLibCheck
enabled. Feel free to clone it and play with it.
git clone https://github.com/remcohaszing/skiplibcheck.git
cd skiplibcheck
npm install
npx tsc
For example, try disabling skipLibCheck
, rename types.d.ts
to types.ts
, or try to add more type errors.