Shipping an npm package without TypeScript declarations means every consumer is flying blind. IDEs show any for all imports, type errors go unreported until runtime, and documentation-on-hover disappears entirely. ISO 25010 analysability collapses — developers must clone your repo just to understand your API surface. For TypeScript projects (now the majority of serious npm consumers), a package without .d.ts files is effectively unusable without manual declare module workarounds.
Critical because the absence of type declarations renders the package untyped for all TypeScript consumers, eliminating IDE autocompletion, type checking, and compile-time safety.
Enable declaration generation in tsconfig.json, configure your build tool to emit .d.ts files, and reference them in package.json.
// tsconfig.json
{
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"outDir": "dist"
}
}
// tsup.config.ts
import { defineConfig } from 'tsup'
export default defineConfig({ entry: ['src/index.ts'], format: ['esm', 'cjs'], dts: true })
// package.json
{
"types": "./dist/index.d.ts",
"exports": { ".": { "types": "./dist/index.d.ts" } }
}
Verify declarations exist after build: ls dist/*.d.ts. Declarations auto-typed as any do not satisfy this check.
ID: sdk-package-quality.package-config.type-declarations
Severity: critical
What to look for: Count all public API functions and classes. For each, check whether the package ships .d.ts type declaration files. Look for:
types or typings field in package.json pointing to a .d.ts filetypes condition in exports field entriesdeclaration: true in tsconfig.json or tsconfig.build.jsondts: true, rollup with @rollup/plugin-dts).d.ts files in the dist/ or output directoryPass criteria: The package includes TypeScript declarations via any of: types/typings field in package.json, types condition in exports, or .d.ts files in the published output. The declaration files must cover the public API entry points — 100% of public API surfaces must have TypeScript declaration files (.d.ts). Report: "X public APIs found, all Y have TypeScript declarations."
Fail criteria: No types or typings field, no types condition in exports, declaration not enabled in tsconfig, and no .d.ts files found in build output. OR declarations exist but don't match the actual exports (e.g., types points to a file that doesn't exist).
Skip (N/A) when: The package is written in plain JavaScript with no TypeScript in the project (no tsconfig.json, no .ts files, no @types/* dependencies). Also skip for Python (uses type stubs via py.typed marker or separate *-stubs package), Rust (types are inherent), and Go (types are inherent).
Do NOT pass when: Type declarations exist but are auto-generated with all types as any — declarations must provide meaningful type information.
Detail on fail: "tsconfig.json has declaration: false. No types field in package.json. Consumers using TypeScript will get no type information — all imports will be typed as 'any'." or "types field points to dist/index.d.ts but tsconfig.json does not enable declaration generation and no .d.ts files exist in dist/"
Remediation: Type declarations are the single most important quality signal for TypeScript consumers. Without them, your package provides no IDE autocompletion, no type checking, and no documentation on hover.
// tsconfig.json — enable declarations:
{
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"outDir": "dist"
}
}
// tsup.config.ts — enable dts generation:
import { defineConfig } from 'tsup'
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm', 'cjs'],
dts: true
})
// package.json — point to declarations:
{
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
}
}