dtsroll is a CLI tool for bundling TypeScript declaration (.d.ts) files.
.d.ts files?undefinedSmaller distributionundefined
Tree-shaking removes unused code, keeping only what’s needed and reducing the output size.
undefinedBundle in private dependenciesundefined
Inline types from private dependencies (e.g., monorepo packages) that aren’t accessible to consumers.
undefinedImprove TS performanceundefined
Flattens multiple files into one, reducing TypeScript’s file resolution for type checking.
npm install --save-dev dtsroll
Compile your TypeScript code with declaration (.d.ts) files
tsc), enable declarationPass in the entry declaration file to dtsroll
dtsroll --dry-run dist/index.d.ts
[!CAUTION]
dtsroll is designed to run on compiled output so it modifies files in-place.
- It will modify files you pass in, and files they import.
- Only pass in backed up or generated files
- Start with
--dry-run
If the changes look good, remove the --dry-run flag:
dtsroll dist/index.d.ts
Running dtsroll without specifying input files will auto-detect them from package.json.
Update your package.json to reference .d.ts files and include dtsroll in the build step:
{
"name": "my-package",
"exports": {
+ "types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"scripts": {
+ "build": "tsc && dtsroll"
}
}
By default, dtsroll decides which dependencies to bundle or keep external by analyzing the package.json file. Packages in devDependencies are bundled, and packages in other dependency types are externalized.
When there is no package.json file, you can specify packages to externalize with the --external flag.
@types packagesSome packages need separate @types/* packages for type definitions. In this setup, typically:
dependencies.@types/* package is in devDependencies.Because the main package is in dependencies, dtsroll externalizes it. However, consumers of your package won’t get the type definitions for it because the @types/* package is only in devDependencies.
To fix this, dtsroll will display a warning suggesting you move the @types/* package out of devDependencies.
Display usage instructions.
Simulate the bundling process without modifying the disk and logs what would happen.
If there is no package.json file, you can specify package names to exclude from the bundle.
[!NOTE]
This flag can only be used when there is nopackage.json. It’s better to define dependencies appropriately inpackage.jsoninstead of using this flag.
Provide resolution conditions to target specific entry points in dependencies, similar to Node’s --conditions.
import { dtsroll } from 'dtsroll'
await dtsroll(options as {
/**
* CWD to find the package.json in
* @default process.cwd()
*/
cwd?: string
/**
* Defaults to auto-detecting d.ts files from package.json
*/
inputs?: string[]
/**
* Only used if there's no package.json
* Defaults to auto-detecting dependencies from package.json
*/
external?: string[]
conditions?: string[]
dryRun?: boolean
})
Use it in conjunction with a plugin that generates the initial declaration files like vite-plugin-dts.
import { defineConfig } from 'vitest/config'
import dts from 'vite-plugin-dts'
import { dtsroll } from 'dtsroll/vite'
export default defineConfig({
// ...
plugins: [
// ...
dts(),
dtsroll()
]
})
For package bundling (along with dts bundling), check out pkgroll.