Want to join a thriving community of quality champions? | Check out Shiftsync

Understanding TypeScript’s skipLibCheck Once and For All

On Testim, we value the quality and accuracy of our codebase. For this reason, we have extensive use of TypeScript.…

By Omri Lavi,

On Testim, we value the quality and accuracy of our codebase. For this reason, we have extensive use of TypeScript.

TypeScript has many advanced options that can help you fine-tune the compiler to your project’s requirements. Some of them are more straightforward, like the declaration option. Some of them seem obvious at first glance but have some non-trivial behavior in some scenarios. One of the not-so-clear options is skipLibCheck.

According to the official documentation, this option “Skips type checking of declaration files.” It may appear obvious – but if you’re unfamiliar with it, the behavior might surprise you.

In this short post, I will clarify the behavior and usage of the skipLibCheck option. After reading, you will know the different behaviors of the option and understand when to use it.

TypeScript’s Default Behaviour

Consider the following invalid type, which references a non-existing type:

By default (when skipLibCheck is false), tsc will fail to compile such an error. It doesn’t matter if the file is in node_modules or one of your project’s files. If, for some reason, you reference an external package that has invalid types – tsc will always fail. Since you can’t really modify your dependencies’ code, you won’t be able to compile your project at all. skipLibCheck can help you exactly in these situations.

Introducing skipLibCheck

According to TypeScript’s official documentation, skipLibCheck will “skip type checking of declaration files.” Let’s try clarifying it. When set, skipLibCheck ignores all errors in declaration (d.ts) files, including ones in node_modules. This includes type errors and compilation errors (like invalid syntax). It does not mean that declaration files are being ignored completely. tsc will only ignore errors from these files.

This behavior is a bit confusing for two reasons:

  1. “Skip lib check” suggests that only library-related code will be skipped. This isn’t true – d.ts files that are part of the project will be affected too.
  2. d.ts files aren’t really skipped entirely. As shown in the demo project, valid types coming from d.ts files are never skipped.

Perhaps the name skipDeclarationErrors is more accurate.

With skipLibCheck, tsc will make a “best effort” to handle valid types coming from declaration files, while treating invalid types as any instead of failing.

skipLibCheck – Pros and Cons

Setting skipLibCheck has two main advantages.

The first is that skipLibCheck may decrease compilation time significantly, especially in larger projects.

The second benefit is greater: skipLibCheck may be your only solution in cases where the code doesn’t compile due to a dependency library. If you use a library compiled with a less strict configuration or a different TS version, you may end up with a project that can’t compile. You will probably want to avoid changing your TS version or strictness level for the entire project, just for that library. A better solution will be to set skipLibCheck, which will ignore these (most likely) irrelevant errors.

If you choose using skipLibCheck, you need to understand the caveats. Your code will lose integrity since some libraries’ types may come up as any instead of the actual type. Furthermore, if one library’s types aren’t compatible with another, TypeScript won’t complain about it. Such incompatibilities may show up as runtime errors.

Another important note is that skipLibCheck does not work well under monorepo projects. In fact, this issue made us investigate skipLibCheck in the first place.

When deciding whether to use skipLibCheck or not, remember the considerations above. If you can allow yourself a slower compilation time and your project compiles without any errors, you can keep skipLibCheck disabled. Reconsider enabling the flag If your project grows and compilation gets slower or if you have issues with libraries’ types.

TL;DR

  • When skipLibCheck is enabled, tsc will ignore all errors coming from declaration files (d.ts). Some types may be treated as any due to ignored errors. Valid types will still be checked.
  • If your project compiles quickly and without errors, keep the skipLibCheck option disabled (default value).
  • Enable skipLibCheck if you have errors coming from a library’s code or that the compilation takes too long
  • Monorepo projects still can’t enjoy the benefits of skipLibCheck properly (for now, at least).

Conclusion

skipLibCheck is a popular TypeScript option that can be critical in some projects. It’s important to know how it behaves to avoid surprises. After reading this post, I hope that you’ll have a stronger grasp of this option’s behavior and know when to use it (and when not to).

More resources