unplugin-dts

repository·main·Indexed 23 days ago

https://github.com/qmhc/unplugin-dts

An unplugin that automatically generates TypeScript declaration files (*.d.ts) from .ts(x) or .vue source files. It supports multiple bundlers including Vite, Rollup, Rolldown, Webpack, Rspack, and Esbuild. It provides features for type bundling via bundleTypes, custom output directories with outDirs, and specific support for Vue projects using the 'vue' processor.

Tokens
12.3K
Snippets
33
Records
70
Agent score
76%

What's inside unplugin-dts

  1. Quick Start with unplugin-dts in Vite

    main

    To use unplugin-dts in a Vite project, import the Vite entry point from unplugin-dts/vite and add it to your defineConfig plugins array. This plugin generates type files (*.d.ts) from .ts(x) or .vue source files when building in library mode.

    import dts from 'unplugin-dts/vite'
    
    export default defineConfig({
      plugins: [dts()],
    })
  2. Configure unplugin-dts for Esbuild

    main

    To use unplugin-dts with Esbuild, import the plugin from unplugin-dts/esbuild and add it to the plugins array in your build script.

    import { build } from 'esbuild'
    import dts from 'unplugin-dts/esbuild'
    
    await build({
      entryPoints: ['src/index.ts'],
      format: 'esm',
      outdir: 'dist',
      bundle: true,
      plugins: [dts()],
    })
  3. Configure unplugin-dts for Webpack

    main

    To use unplugin-dts with Webpack, import the plugin from unplugin-dts/webpack and add it to the plugins array in your webpack.config.js.

    import { resolve } from 'node:path'
    import dts from 'unplugin-dts/webpack'
    
    export default {
      entry: {
        index: './src/index.ts',
      },
      output: {
        path: resolve(__dirname, 'dist'),
      },
      module: {
        rules: [
          {
            test: /\.ts$/,
            use: 'ts-loader',
            exclude: /node_modules/,
          },
        ],
      },
      plugins: [dts()],
    }
  4. Inline types from internal monorepo packages

    main

    In a monorepo, if Package A depends on an unpublished Package B, the generated .d.ts files for Package A might still contain import { ... } from 'packageB', which will fail for consumers.

    Configure the plugin to process the source code of the internal package instead of its build output. This ensures TypeScript treats the types as part of Package A.

    vite.config.ts:

    import { defineConfig } from 'vite'
    import dts from 'vite-plugin-dts'
    import { resolve } from 'node:path'
    
    export default defineConfig({
      resolve: {
        alias: {
          // Point to the source entry of the internal package
          'packageB': resolve(__dirname, '../packageB/src/index.ts'),
        },
      },
      plugins: [
        dts({
          // Include the internal package's source files so they are emitted together
          include: ['src', '../packageB/src'],
          tsconfigPath: resolve(__dirname, 'tsconfig.app.json'),
        }),
      ],
    })

    tsconfig.app.json:

    {
      "compilerOptions": {
        "paths": {
          "packageB": ["../packageB/src/index.ts"]
        }
      }
    }

    Note: Ensure the internal package's package.json has a valid version field.

    Method 2: Use bundleTypes.bundledPackages

    If bundleTypes: true is enabled, you can instruct @microsoft/api-extractor to inline specific packages.

    dts({
      bundleTypes: {
        bundledPackages: ['packageB', '@scope/*'],
      },
    })

    Limitations of Method 2:

    • It forces all declarations into a single rolled-up file per entry, which is problematic for multi-entry libraries.
    • It may fail to inline complex types (e.g., cross-file re-exports or Vue-specific types) with an "Unable to follow symbol" error.
    import { defineConfig } from 'vite'
    import dts from 'vite-plugin-dts'
    import { resolve } from 'node:path'
    
    export default defineConfig({
      resolve: {
        alias: {
          'packageB': resolve(__dirname, '../packageB/src/index.ts'),
        },
      },
      plugins: [
        dts({
          include: ['src', '../packageB/src'],
          tsconfigPath: resolve(__dirname, 'tsconfig.app.json'),
        }),
      ],
    })
  5. Use unplugin-dts with Vue

    main

    To use unplugin-dts in a Vue project, you must install @vue/language-core as a peer dependency:

    pnpm i -D @vue/language-core

    While the plugin automatically detects .vue files and uses the 'vue' processor, it is recommended to explicitly set the processor option to 'vue'.

    export default defineConfig({
      plugins: [dts({ processor: 'vue' })],
    })
  6. Quick Start with Vite

    main

    To use unplugin-dts in a Vite project, import the Vite-specific entry point from unplugin-dts/vite and add it to your defineConfig plugins array. This plugin generates declaration files (*.d.ts) from .ts(x) or .vue source files, which is particularly useful when building libraries in library mode.

    import dts from 'unplugin-dts/vite'
    
    export default defineConfig({
      plugins: [dts()],
    })
  7. Install unplugin-dts

    main

    Install unplugin-dts as a development dependency using pnpm. Note that this project requires Node.js >= 20.

    If you are using Vite and want the specific Vite wrapper, you can use vite-plugin-dts, but using unplugin-dts is the recommended approach as it is more universal.

    pnpm i -D unplugin-dts
  8. Migrate from vite-plugin-dts v4 to v5 / unplugin-dts v1

    main

    When upgrading from vite-plugin-dts v4 to v5 (or moving to unplugin-dts v1), several breaking changes in configuration keys and import paths must be addressed.

    Import Path Changes

    While vite-plugin-dts maintains a compatibility layer for Vite, the recommended approach for v5 is to use unplugin-dts directly.

    • Vite (Compatibility): import dts from 'vite-plugin-dts'
    • Vite (Recommended): import dts from 'unplugin-dts/vite'
    • Rollup: import dts from 'unplugin-dts/rollup'

    Configuration Renames

    Old Option (v4)New Option (v5)Description
    rollupTypesbundleTypesControls type bundling. Now supports boolean | object.
    outDiroutDirsSpecifies output directories. Now supports moduleFormat.
    rollupConfigbundleTypes.extractorConfigNested within bundleTypes.
    rollupOptionsbundleTypes.invokeOptionsNested within bundleTypes.
    bundledPackagesbundleTypes.bundledPackagesMoved from top-level to nested within bundleTypes.
    logLevelRemovedNo longer configurable.

    Unchanged API

    • editSourceMapDir: (content: string, fromDir: string, toDir: string) => string
    • Resolver type: { name: string, supports: boolean, transform: ... }
    // v5 (unplugin-dts, recommended)
    import dts from 'unplugin-dts/vite'
    import { type PluginOptions, editSourceMapDir } from 'unplugin-dts'
    
    export { type PluginOptions, editSourceMapDir }
  9. Configure unplugin-dts for Rspack

    main

    To use unplugin-dts with Rspack, import the plugin from unplugin-dts/rspack and add it to the plugins array in your rspack.config.mjs.

    import { resolve } from 'node:path'
    import { fileURLToPath } from 'node:url'
    import { defineConfig } from '@rspack/cli'
    import dts from 'unplugin-dts/rspack'
    
    const rootDir = resolve(fileURLToPath(import.meta.url), '..')
    
    export default defineConfig({
      entry: {
        index: './src/index.ts',
      },
      output: {
        path: resolve(rootDir, 'dist'),
      },
      module: {
        rules: [
          {
            test: /\.js$/,
            use: [
              {
                loader: 'builtin:swc-loader',
                options: {
                  jsc: {
                    parser: {
                      syntax: 'ecmascript',
                    },
                  },
                },
              },
            ],
          },
          {
            test: /\.ts$/,
            use: [
              {
                loader: 'builtin:swc-loader',
                options: {
                  jsc: {
                    parser: {
                      syntax: 'typescript',
                      decorators: true,
                    },
                  },
                },
              },
            ],
          },
        ],
      },
      plugins: [dts()],
    })