reactjs - Build .d.ts declaration files with Vite - Stack Overflow

admin2025-05-01  1

I am struggling getting Vite to generate .d.ts declaration files for my React TypeScript library. After running npm run build only the main.js and main.css files are present in the dist folder.

I do see that during the build several files including .d.ts files are created in the dist/ folder but when the build is done everything is removed again and only the main.js file and main.css file remain there.

I've tried to change or omit the values for: noEmit, declaration, declarationMap and emitDeclarationOnly from the tsconfig.app.json but without success. None of the examples I find on the internet seem to work.

My project structure

package.json
tsconfig.json
tsconfig.app.json
tsconfig.node.json
vite.config.js
/src/main.ts
/src/SomeComponent.tsx
/src/SomeHook.ts

Vite should create a dist/ folder that contains a main.js file and a main.d.ts file that contains all the type information for the react SomeComponent and SomeHook.

My main.ts

export { SomeComponent } from './SomeComponent';
export { useSomeHook } from './useSomeHook';

Example of useSomeHook.ts:

type UseSomeHookProps = {
  someArg?: () => void;
};
export const useSomeHook = ({ someArg }: UseSomeHookProps = {}) => {
  return { ... };
};

My Vite config

/// <reference types="vite/client" />

import { defineConfig } from 'vite'
import { libInjectCss } from 'vite-plugin-lib-inject-css'
import react from '@vitejs/plugin-react'
import dts from 'vite-plugin-dts'

export default defineConfig({
  plugins: [
    react(),
    libInjectCss(),
    dts({
      entryRoot: 'src',
      outDir: 'dist',
    }),
  ],
  build: {
    lib: {
      entry: './src/main.ts',
      name: 'ReactWizard',
      fileName: 'main',
      formats: ['es'],
     
    },
    rollupOptions: {
      external: ['react', 'react-dom', 'react/jsx-runtime'],
      output: {
        globals: {
          react: 'React',
          'react-dom': 'React-dom',
          'react/jsx-runtime': 'react/jsx-runtime',
        },
      },
    },
  },
})

My tsconfig.app.json

{
  "compilerOptions": {
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "noEmit": false,
    "jsx": "react-jsx",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedSideEffectImports": true,

    "declaration": true,
    "declarationMap": true,
    "emitDeclarationOnly": true,
    "outDir": "dist",
  },
  "include": ["src"],
}

My package.json

{
  "name": "some-package",
  "version": "0.0.0",
  "type": "module",
  "files": [
    "dist"
  ],
  "exports": "./dist/main.js",
  "module": "./dist/main.js",
  "types": "./dist/main.d.ts",
  "scripts": {
    "build": "tsc -b && vite build",
    ...
  },
  "dependencies": {
    ...
  },
  "devDependencies": {
    "@vitejs/plugin-react": "^4.3.4",
    "typescript": "~5.6.2",
    "vite": "^6.0.5",
    "vite-plugin-dts": "^4.4.0",
    ...
  }
}

Terminal output

The terminal output when runningnpm run build is:

> tsc -b && vite build

vite v6.0.6 building for production...
✓ 189 modules transformed.

[vite:dts] Start generate declaration files...
computing gzip size (0)...[vite:dts] Declaration files built in 1074ms.

dist/main.css   6.63 kB │ gzip: 1.74 kB
dist/main.js   23.50 kB │ gzip: 7.85 kB
✓ built in 1.97s

I am struggling getting Vite to generate .d.ts declaration files for my React TypeScript library. After running npm run build only the main.js and main.css files are present in the dist folder.

I do see that during the build several files including .d.ts files are created in the dist/ folder but when the build is done everything is removed again and only the main.js file and main.css file remain there.

I've tried to change or omit the values for: noEmit, declaration, declarationMap and emitDeclarationOnly from the tsconfig.app.json but without success. None of the examples I find on the internet seem to work.

My project structure

package.json
tsconfig.json
tsconfig.app.json
tsconfig.node.json
vite.config.js
/src/main.ts
/src/SomeComponent.tsx
/src/SomeHook.ts

Vite should create a dist/ folder that contains a main.js file and a main.d.ts file that contains all the type information for the react SomeComponent and SomeHook.

My main.ts

export { SomeComponent } from './SomeComponent';
export { useSomeHook } from './useSomeHook';

Example of useSomeHook.ts:

type UseSomeHookProps = {
  someArg?: () => void;
};
export const useSomeHook = ({ someArg }: UseSomeHookProps = {}) => {
  return { ... };
};

My Vite config

/// <reference types="vite/client" />

import { defineConfig } from 'vite'
import { libInjectCss } from 'vite-plugin-lib-inject-css'
import react from '@vitejs/plugin-react'
import dts from 'vite-plugin-dts'

export default defineConfig({
  plugins: [
    react(),
    libInjectCss(),
    dts({
      entryRoot: 'src',
      outDir: 'dist',
    }),
  ],
  build: {
    lib: {
      entry: './src/main.ts',
      name: 'ReactWizard',
      fileName: 'main',
      formats: ['es'],
     
    },
    rollupOptions: {
      external: ['react', 'react-dom', 'react/jsx-runtime'],
      output: {
        globals: {
          react: 'React',
          'react-dom': 'React-dom',
          'react/jsx-runtime': 'react/jsx-runtime',
        },
      },
    },
  },
})

My tsconfig.app.json

{
  "compilerOptions": {
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "noEmit": false,
    "jsx": "react-jsx",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedSideEffectImports": true,

    "declaration": true,
    "declarationMap": true,
    "emitDeclarationOnly": true,
    "outDir": "dist",
  },
  "include": ["src"],
}

My package.json

{
  "name": "some-package",
  "version": "0.0.0",
  "type": "module",
  "files": [
    "dist"
  ],
  "exports": "./dist/main.js",
  "module": "./dist/main.js",
  "types": "./dist/main.d.ts",
  "scripts": {
    "build": "tsc -b && vite build",
    ...
  },
  "dependencies": {
    ...
  },
  "devDependencies": {
    "@vitejs/plugin-react": "^4.3.4",
    "typescript": "~5.6.2",
    "vite": "^6.0.5",
    "vite-plugin-dts": "^4.4.0",
    ...
  }
}

Terminal output

The terminal output when runningnpm run build is:

> tsc -b && vite build

vite v6.0.6 building for production...
✓ 189 modules transformed.

[vite:dts] Start generate declaration files...
computing gzip size (0)...[vite:dts] Declaration files built in 1074ms.

dist/main.css   6.63 kB │ gzip: 1.74 kB
dist/main.js   23.50 kB │ gzip: 7.85 kB
✓ built in 1.97s
Share Improve this question edited Jan 2 at 20:08 Stefan asked Jan 2 at 15:34 StefanStefan 1,3274 gold badges14 silver badges31 bronze badges 2
  • What is your build process? Presumably you have tsc then vite build in your package.json's scripts somewhere (per e.g. vite.dev/guide/features.html#typescript), and Vite empties the output directory by default. – jonrsharpe Commented Jan 2 at 15:43
  • Correct. I added my package.json to the question. I don't get the emptyOutDir setting though, Vite's dts plugin is supposed to build the declaration files right, so why would it empty it afterwards, and how come the main.css file isn't emptied out? – Stefan Commented Jan 2 at 20:16
Add a comment  | 

1 Answer 1

Reset to default 3

I had the exact same issue was able to solve it by adding tsConfigPath. This is mentioned in the usage of the plugin.

If you start with official Vite template, you should specify the tsconfigPath:

{
  plugins: [dts({ tsconfigPath: './tsconfig.app.json' })]
}

Reference: https://github.com/qmhc/vite-plugin-dts

转载请注明原文地址:http://www.anycun.com/QandA/1746109479a91799.html