TypeScript adds a second dependency set on top of npm's: type declaration packages, usually under @types, plus compiler options that decide how strictly they are checked. Manage both. Keep types out of production installs, review type packages like any other code, and know what skipLibCheck hides.
Why is TypeScript different from plain JavaScript?
The runtime packages are the same as in JavaScript, with the same lockfile, audit and install script questions. What TypeScript adds is declaration files that describe those packages to the compiler, and the toolchain itself: the compiler, linters, bundlers and plugins. These mostly run on developer machines and build servers, which hold publish tokens and source code. A malicious dev dependency has a better view of your secrets than a production one.
Where do type packages come from?
The DefinitelyTyped repository describes itself as "the repository for high quality TypeScript type definitions". Its documentation says installing through npm is the preferred method, for example npm install --save-dev @types/node. For a scoped module, drop the at sign and add a double underscore after the scope, so typings for @babel/preset-env are @types/babel__preset-env.
Two security points follow. First, @types packages are separate packages from the library they describe, published by different people. Check that the name matches the library exactly, since a near miss spelling is the classic typosquat. Second, a type package normally contains only declarations, so a package under @types that contains install scripts or executable code deserves immediate attention.
Should type packages be dev dependencies?
Yes in most applications. The DefinitelyTyped example uses --save-dev, which keeps them out of production installs. A constructed example: a service lists 40 @types packages in dependencies, so its container image carries them all, plus each one's own dependencies. Moving them to devDependencies shrinks the image and the scan results.
The exception is a library that exposes types from another package in its own public declarations. Consumers then need those types, and the dependency belongs in the regular or peer set.
What does skipLibCheck do?
The TypeScript reference describes skipLibCheck as skipping type checking of declaration files, which saves compile time at the expense of type system accuracy, and gives the example of two libraries defining the same type inconsistently. TypeScript then checks only the code you reference, not each declaration file.
It is a convenient setting, and its cost is that a mismatch between a package and its types can go unnoticed. That is a correctness risk more than a direct security one, but a wrong type on a function that sanitises input can mislead reviewers. Turn it on knowingly, and try with it off when you upgrade major versions.
What applies from the JavaScript side?
All of it. Commit the lockfile, install with npm ci, audit with a failure threshold, and decide on install scripts for CI. Be strict about the build tooling: pin the TypeScript version exactly so a compiler change does not alter output in a release, and review plugin updates for bundlers and linters.
How to check or apply this
- List every
@typespackage and confirm each matches a real library you use. - Move type packages to dev dependencies unless your public types need them.
- Remove
@typespackages for libraries that now ship their own declarations. - Review whether
skipLibCheckis on and why. - Pin the compiler and build plugins exactly, and review their lockfile diffs.
- Run audit and signature checks in CI over dev and production sets, but report them separately.
- Produce a dependency inventory for each release split into runtime and tooling.
Quick check
Are @types packages safe because they only contain types?
Usually they hold only declarations, but they are still third party packages. Verify the name and check for scripts or code that should not be there.
Does skipLibCheck make the build insecure?
Not directly. It reduces type checking of declaration files, so a mismatch between a package and its types may go unnoticed.
Sources
- DefinitelyTyped repository
- TypeScript, tsconfig reference
- npm Docs, package-lock.json
- npm Docs, npm ci
Last reviewed: 18 October 2026.