如何让TypeScript不为环境声明文件生成/// <reference path="…" />指令?
解决TypeScript自动生成三斜线引用导致的包使用者编译错误
背景
我在使用Lit开发npm包时,为避免在模板中意外插入无效值,编写了src/lit.d.ts文件来增强html标签函数的类型校验:
declare module "lit" { import { html as htmlFromLit } from "lit/index"; export * from "lit/index"; export const html: (strings: TemplateStringsArray, ...values: Array<string | number /* 可扩展其他允许的类型 */>) => ReturnType<typeof htmlFromLit>; }
这样开发时既能保持标准的import { html } from "lit"写法,又能获得比Lit默认更强的类型安全:
import { html } from "lit"; export const h = html`<p>${null}</p>`; // ~~~~ 类型“null”的参数不能赋给类型“string | number”的参数。
问题
包的使用者遇到了如下编译错误:
node_modules/my-package/dist/index.d.ts:1:22 - error TS6053: File '/…/consuming-project/node_modules/my-package/src/lit.d.ts' not found. 1 /// <reference path="../src/lit.d.ts" /> ~~~~~~~~~~~~~~~
生成的dist/index.d.ts中自动添加了这条三斜线引用,但src目录并未包含在发布的npm包中。而且lit.d.ts仅用于我开发时的类型校验,完全不需要发布给使用者。手动删除这条引用后,使用者的项目就能正常编译,该问题在TypeScript 4.9.5和5.0.4版本中均存在。
项目详情
文件结构
. ├── package.json ├── package-lock.json ├── src │ ├── index.ts │ └── lit.d.ts └── tsconfig.json
package.json
{ "name": "my-package", "version": "0.0.0", "scripts": { "build": "rimraf dist && tsc -p ." }, "files": [ "dist/**/*" ], "type": "module", "main": "dist/index.js", "devDependencies": { "rimraf": "^3.0.2", "typescript": "^4.7.4" }, "dependencies": { "lit": "^2.4.1" } }
tsconfig.json
{ "compilerOptions": { "declaration": true, "module": "es2015", "moduleResolution": "node", "outDir": "dist", "strict": true, "target": "es2019" }, "include": [ "src/**/*.ts" ] }
解决方案
方法1:隔离自定义类型文件
将lit.d.ts移动到src/@types/lit/index.d.ts路径下,然后修改tsconfig.json,让TypeScript仅在开发阶段识别该自定义类型,编译时排除它:
{ "compilerOptions": { // 保留原有配置 "typeRoots": ["./src/@types", "./node_modules/@types"] }, "include": [ "src/**/*.ts" ], "exclude": [ "src/@types/**/*.d.ts" ] }
这种方式下,开发时能正常使用增强的类型校验,编译生成声明文件时不会引入自定义类型的引用。
方法2:编译后自动清理三斜线引用
修改package.json的build脚本,在编译完成后自动移除声明文件中的目标引用:
- macOS/Linux环境:
{ "scripts": { "build": "rimraf dist && tsc -p . && sed -i '' '/\\/\\/\\/ <reference path=\"\\.\\.\\/src\\/lit\\.d\\.ts\" \\/>/d' dist/index.d.ts" } }
- Windows环境:
{ "scripts": { "build": "rimraf dist && tsc -p . && (Get-Content dist/index.d.ts) -replace '/// <reference path=\"../src/lit.d.ts\" />', '' | Set-Content dist/index.d.ts" } }
这种方式直接在构建流程中清理掉自动生成的无效引用,简单直接。
方法3:标记自定义类型为开发专用
在lit.d.ts顶部添加注释,让TypeScript在生成声明文件时忽略该模块的影响:
// @ts-ignore declare module "lit" { import { html as htmlFromLit } from "lit/index"; export * from "lit/index"; export const html: (strings: TemplateStringsArray, ...values: Array<string | number /* etc */>) => ReturnType<typeof htmlFromLit>; }
注意:这种方法可能会在某些场景下影响开发时的类型校验,优先级低于前两种方案。
内容的提问来源于stack exchange,提问作者Simon Alling
相关产品推荐
相关产品推荐

