Declaration Files (dts)

TypeScript declaration file generation and isolated declarations in Packem

Declaration Files (dts)

Packem provides comprehensive TypeScript declaration file generation with support for both traditional and isolated declarations. Declaration files (.d.ts) are essential for TypeScript libraries to provide type information to consumers.

Automatic Detection

Packem automatically enables declaration file generation when it detects TypeScript usage in your project:

  • TypeScript files (.ts, .tsx) in your source code
  • types or typings field in your package.json
  • tsconfig.json file in your project
{
  "name": "my-library",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    }
  }
}

Configuration

Enable/Disable Declaration Generation

import { defineConfig } from '@visulima/packem/config'

export default defineConfig({
  // Explicitly enable declaration generation
  declaration: true,
  
  transformer: 'esbuild'
})

Advanced Declaration Options

export default defineConfig({
  declaration: {
    // Generate declaration files
    enabled: true,
    
    // Output directory for declarations
    outDir: 'types',
    
    // Generate declaration maps for better debugging
    declarationMap: true,
    
    // Include comments in declaration files
    removeComments: false,
    
    // Emit declarations only (no JS output)
    emitDeclarationOnly: false
  }
})

Isolated Declarations

Isolated declarations are a TypeScript 5.5+ feature that dramatically improves declaration generation performance by avoiding expensive type inference.

Isolated declarations can be 10-100x faster than traditional declaration generation for large projects.

Enable Isolated Declarations

import { defineConfig } from '@visulima/packem/config'
import isolatedDeclarations from '@visulima/packem/dts/isolated/transformer/typescript'

export default defineConfig({
  isolatedDeclarationTransformer: isolatedDeclarations,
  transformer: 'esbuild'
})

Available Isolated Declaration Transformers

import isolatedDeclarations from '@visulima/packem/dts/isolated/transformer/typescript'

export default defineConfig({
  isolatedDeclarationTransformer: isolatedDeclarations,
  transformer: 'esbuild'
})
import isolatedDeclarations from '@visulima/packem/dts/isolated/transformer/swc'

export default defineConfig({
  isolatedDeclarationTransformer: isolatedDeclarations,
  transformer: 'swc'
})
import isolatedDeclarations from '@visulima/packem/dts/isolated/transformer/oxc'

export default defineConfig({
  isolatedDeclarationTransformer: isolatedDeclarations,
  transformer: 'oxc'
})

Isolated Declarations Requirements

For isolated declarations to work, your TypeScript code must follow certain patterns:

// ✅ Good - Explicit return types
export function greet(name: string): string {
  return `Hello, ${name}!`
}

// ✅ Good - Explicit interface
export interface User {
  id: number
  name: string
}

// ❌ Bad - Inferred return type
export function greet(name: string) {
  return `Hello, ${name}!`
}

// ❌ Bad - Inferred type
export const config = {
  apiUrl: 'https://api.example.com'
}

// ✅ Good - Explicit type
export const config: { apiUrl: string } = {
  apiUrl: 'https://api.example.com'
}

Isolated declarations require explicit type annotations on all exported declarations. This is a TypeScript compiler requirement, not a Packem limitation.

Declaration File Formats

Packem generates declaration files that match your output formats:

ESM/CJS Dual Package

{
  "exports": {
    ".": {
      "import": {
        "types": "./dist/index.d.mts",
        "default": "./dist/index.mjs"
      },
      "require": {
        "types": "./dist/index.d.cts",
        "default": "./dist/index.cjs"
      }
    }
  }
}

Packem will generate:

  • dist/index.d.mts - ESM declaration file
  • dist/index.d.cts - CJS declaration file

Legacy Node.js Compatibility

export default defineConfig({
  rollup: {
    node10Compatibility: {
      typeScriptVersion: '>=5.0',
      writeToPackageJson: true
    }
  }
})

This generates typeVersions in your package.json for Node.js 10 compatibility:

{
  "types": "./dist/index.d.ts",
  "typesVersions": {
    ">=5.0": {
      "*": ["./dist/index.d.ts"]
    }
  }
}

Declaration Bundling

Bundle multiple declaration files into a single file:

export default defineConfig({
  declaration: {
    enabled: true,
    bundle: true, // Bundle all declarations into one file
    outFile: 'dist/index.d.ts'
  }
})

Declaration Bundling with rollup-plugin-dts

import dts from 'rollup-plugin-dts'

export default defineConfig({
  rollup: {
    plugins: [
      dts({
        // Bundle all .d.ts files
        bundledPackages: ['my-dependency'],
        // Respect external dependencies
        respectExternal: true
      })
    ]
  }
})

Multiple Entry Points

Generate declarations for multiple entry points:

export default defineConfig({
  entry: {
    index: 'src/index.ts',
    utils: 'src/utils.ts',
    cli: 'src/cli.ts'
  },
  
  declaration: true
})

This generates:

  • dist/index.d.ts
  • dist/utils.d.ts
  • dist/cli.d.ts

Declaration Maps

Enable declaration maps for better IDE support:

export default defineConfig({
  declaration: {
    enabled: true,
    declarationMap: true
  }
})

Declaration maps allow IDEs to navigate from compiled declaration files back to the original TypeScript source.

External Dependencies

Handle external dependencies in declarations:

export default defineConfig({
  rollup: {
    external: ['react', 'lodash'],
    
    // Ensure externals are preserved in declarations
    dts: {
      external: ['react', 'lodash']
    }
  }
})

Path Mapping

Resolve TypeScript path mappings in declarations:

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@utils/*": ["src/utils/*"]
    }
  }
}
// src/index.ts
import { helper } from '@utils/helper'
import { Component } from '@/components/Component'

Packem automatically resolves these paths in the generated declarations.

Validation

Validate your declaration files with external tools:

export default defineConfig({
  declaration: true,
  
  hooks: {
    'build:after': async () => {
      // Run attw (Are The Types Wrong?)
      await import('@arethetypeswrong/core').then(({ analyze }) => {
        return analyze('./package.json')
      })
    }
  }
})

Performance Optimization

Use Isolated Declarations

For maximum performance, use isolated declarations:

export default defineConfig({
  // Use isolated declarations for speed
  isolatedDeclarationTransformer: isolatedDeclarations,
  
  // Use fast transformer for JavaScript
  transformer: 'esbuild'
})

Incremental Compilation

Enable TypeScript incremental compilation:

// tsconfig.json
{
  "compilerOptions": {
    "incremental": true,
    "tsBuildInfoFile": ".tsbuildinfo"
  }
}

Parallel Processing

Process multiple entry points in parallel:

export default defineConfig({
  entry: {
    index: 'src/index.ts',
    utils: 'src/utils.ts',
    cli: 'src/cli.ts'
  },
  
  declaration: {
    enabled: true,
    parallel: true // Process declarations in parallel
  }
})

Troubleshooting

Declaration Generation Fails

  1. Check TypeScript version: Ensure you're using TypeScript 4.5 or later
  2. Verify tsconfig.json: Ensure your TypeScript configuration is valid
  3. Check for type errors: Fix any TypeScript compilation errors
  4. Use explicit types: For isolated declarations, ensure all exports have explicit types

Missing Types

// Add explicit return type
export function myFunction(): string {
  return 'hello'
}

// Add explicit interface
export interface MyConfig {
  apiUrl: string
}

Path Resolution Issues

Ensure your tsconfig.json paths are correctly configured:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  },
  "include": ["src/**/*"]
}

Performance Issues

  1. Use isolated declarations for large projects
  2. Enable incremental compilation in TypeScript
  3. Exclude test files from declaration generation
  4. Use declaration bundling to reduce file count

Examples

Basic Library

export default defineConfig({
  transformer: 'esbuild',
  declaration: true
})

React Component Library

export default defineConfig({
  transformer: 'esbuild',
  
  esbuild: {
    jsx: 'automatic',
    jsxImportSource: 'react'
  },
  
  declaration: {
    enabled: true,
    declarationMap: true
  },
  
  rollup: {
    external: ['react', 'react-dom']
  }
})

High-Performance Library

import isolatedDeclarations from '@visulima/packem/dts/isolated/transformer/typescript'

export default defineConfig({
  isolatedDeclarationTransformer: isolatedDeclarations,
  transformer: 'esbuild',
  
  declaration: {
    enabled: true,
    parallel: true
  }
})

  • Transformers - Choose compatible transformers
  • Output Format - Match declaration formats to output formats
  • TSConfig - TypeScript configuration integration
  • Package Exports - Automatic exports generation
Support

Contribute to our work and keep us going

Community is the heart of open source. The success of our packages wouldn't be possible without the incredible contributions of users, testers, and developers who collaborate with us every day.Want to get involved? Here are some tips on how you can make a meaningful impact on our open source projects.

Ready to help us out?

Be sure to check out the package's contribution guidelines first. They'll walk you through the process on how to properly submit an issue or pull request to our repositories.

Submit a pull request

Found something to improve? Fork the repo, make your changes, and open a PR. We review every contribution and provide feedback to help you get merged.

Good first issues

Simple issues suited for people new to open source development, and often a good place to start working on a package.
View good first issues