This TypeScript error occurs when you try to use both skipLibCheck and declaration compiler options together. skipLibCheck skips type checking of declaration files, but declaration requires checking library types to generate accurate .d.ts files. The fix involves choosing one option or using alternative approaches for faster builds.
TypeScript's `skipLibCheck` and `declaration` options have a fundamental conflict: **skipLibCheck: true** - Skips type checking of all declaration files (*.d.ts) from node_modules - Speeds up compilation by ignoring library type errors - Useful when you trust library types or need faster builds **declaration: true** - Generates .d.ts declaration files from your TypeScript source - Requires TypeScript to fully analyze and check library types - Essential for publishing TypeScript libraries The conflict arises because: 1. When generating declarations (`declaration: true`), TypeScript needs to understand the complete type system 2. This includes checking library declaration files to ensure your generated .d.ts files are type-safe 3. `skipLibCheck: true` prevents this necessary checking, creating a contradiction TypeScript enforces this restriction to prevent generating incorrect or unsafe declaration files that could break downstream consumers of your library.
First, decide what's more important for your project:
- Need declaration files (publishing a library): Remove skipLibCheck or set it to false
- Need faster builds (development/testing): Remove declaration or set it to false
Update your tsconfig.json accordingly:
For declaration generation (library publishing):
{
"compilerOptions": {
"declaration": true,
"skipLibCheck": false // Required for accurate .d.ts generation
}
}For faster builds (development):
{
"compilerOptions": {
"declaration": false,
"skipLibCheck": true // Speeds up compilation
}
}Create multiple TypeScript configs for different purposes:
tsconfig.json (development, fast):
{
"compilerOptions": {
"skipLibCheck": true,
"declaration": false
}
}tsconfig.build.json (production/library):
{
"extends": "./tsconfig.json",
"compilerOptions": {
"skipLibCheck": false,
"declaration": true,
"outDir": "./dist"
}
}Then use them appropriately:
# Fast development builds
npx tsc
# Production/library builds with declarations
npx tsc --project tsconfig.build.jsonIf your tsconfig extends another config, check what options it sets:
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"declaration": true // May conflict with skipLibCheck in base
}
}Check the base config:
cat tsconfig.base.json | grep -A5 '"skipLibCheck"'If the base has skipLibCheck: true, explicitly override it:
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"skipLibCheck": false, // Override inherited value
"declaration": true
}
}In a monorepo with multiple packages, each package may need different settings:
Library package (needs declarations):
// packages/my-library/tsconfig.json
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"skipLibCheck": false,
"declaration": true,
"outDir": "./dist"
}
}App package (development speed):
// apps/my-app/tsconfig.json
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"skipLibCheck": true,
"declaration": false,
"outDir": "./build"
}
}Ensure your build scripts reference the correct configs:
# Build library with declarations
cd packages/my-library && tsc --project tsconfig.json
# Build app without declarations
cd apps/my-app && tsc --project tsconfig.jsonIf you need both speed and declarations, try these alternatives:
1. Use incremental compilation:
{
"compilerOptions": {
"incremental": true,
"declaration": true,
"skipLibCheck": false
}
}2. Enable declarationMap instead of full rechecks:
{
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"skipLibCheck": false
}
}3. Use project references for large codebases:
{
"references": [
{ "path": "./packages/core" },
{ "path": "./packages/utils" }
],
"compilerOptions": {
"composite": true,
"declaration": true,
"skipLibCheck": false
}
}4. Run type checking separately from building:
# Type check (can use skipLibCheck)
npx tsc --noEmit --skipLibCheck
# Build with declarations (no skipLibCheck)
npx tsc --declarationTest your updated configuration:
# If you removed skipLibCheck for declarations
npx tsc --declaration
# If you removed declaration for speed
npx tsc --skipLibCheck
# For separate config approach
npx tsc --project tsconfig.build.jsonCheck that:
- No TS5054 error appears
- Declaration files are generated (if declaration: true)
- Build completes successfully
- Output files are correct
For libraries, test the generated declarations:
# Check if .d.ts files exist
ls -la dist/*.d.ts
# Test type checking with the generated declarations
npx tsc --noEmit --project test-consumer/### Understanding the Technical Conflict
The skipLibCheck option tells TypeScript: "Don't check the types in library declaration files (*.d.ts from node_modules)." This includes:
- Standard library types (lib.d.ts)
- Third-party library types (@types/* packages)
- Any .d.ts files TypeScript would normally verify
When declaration: true is set, TypeScript needs to:
1. Analyze your code's types completely
2. Understand how your types interact with library types
3. Generate accurate .d.ts files that reflect these interactions
If library types aren't checked (skipLibCheck: true), TypeScript might:
- Generate declarations with incorrect type references
- Miss type errors that would appear in downstream code
- Create unsafe type definitions
### Performance Trade-offs
With skipLibCheck: false (required for declaration: true):
- ✅ Accurate type checking
- ✅ Safe declaration generation
- ❌ Slower compilation (checks all library types)
With skipLibCheck: true (cannot use declaration: true):
- ✅ Faster compilation
- ✅ Useful for development/CI
- ❌ No declaration file generation
- ❌ Potential missed type errors
### Workarounds for Large Projects
1. Composite projects: Break into smaller projects with project references
2. Incremental builds: Use incremental: true to cache compilation results
3. Selective checking: Use skipDefaultLibCheck: true instead (skips only standard lib)
4. Build pipelines: Separate type checking from declaration generation
### Version Considerations
- TypeScript 3.0+: Introduced stricter checking of this conflict
- TypeScript 4.0+: Improved error messages for conflicting options
- Always check your TypeScript version's documentation for option compatibility
Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript