在 TS 项目中,有太多一样的类型声明,重复声明显然是最不明智的选择。还有一种方式就是采用 export,import 方式。但是每个使用的文件都需要 imort,或者一个文件需要 import 多个类型声明,都会显得代码冗杂。所以我们可以在项目中采用在 d.ts 文件中声明全局声明命名空间的方式。
但是在组件库项目中,就会遇到打包后找不到命名空间的问题。
一、全局命名空间使用
声明
declare namespace Feature { export type BreadcrumbItem = { id: string; label: string; } }
使用
type IProps = { data: Feature.BreadcrumbItem[]; } const Breadcrumb: React.FC<IProps> = (props) => { return <div>{props.id}</div> }
二、 解决打包后命名空间失效问题
问题一:打包后 d.ts 文件丢失
原因:.d.ts
文件被视为编译器进行类型检查的不可修改的输入。它们不用于任何输出生成,这也意味着它们不会被复制到build
。
The .d.ts files you use are an input to the build system but not an output. It’s perfectly reasonable to consume some types from a .d.ts but have your output not use those types, so there’d be no reason to distribute the input .d.ts with your build results. […] It sounds like you’ll want a post-build step in your build tool to copy the relevant .d.ts files wherever you need them.The .d.ts files are considered “references” the compiler will not touch them, not move them, or recreate them. An easy way to think of the .d.ts files is that they go along with your .js files. if you are copying the .js files, you should copy the matching .d.ts.
解决:通过手动构建步骤复制 d.ts 文件。
我构建工具用的是 gulp,其他构建工具操作类似:
gulp.task('copy', done => { return gulp.src('src/typings/*')//需要被复制的文件夹 .pipe(gulp.dest('lib/typings'));//复制后输出位置 });
问题二:d.ts 文件打包输出后,全局命名未生效
原因一:打包后的 d.ts 文件未编译
解决:修改 tsconfig.json 文件
{ "compilerOptions": { "module": "commonjs", "lib": [ "es6" ], "noImplicitAny": true, "noImplicitThis": true, "strictNullChecks": true, "strictFunctionTypes": true, "baseUrl": "../", "typeRoots": [ "../" ], "types": [], "noEmit": true, "forceConsistentCasingInFileNames": true }, "include": [ "./lib" //需要 ts 编译的文件夹 ], }
原因二:打包后的 d.ts 文件未引入
1. package.json
中的 types
或 typings
字段指定一个类型声明文件地址。比如:
{ "name": "foo", "version": "1.0.0", "main": "lib/index.js", "types": "index.d.ts", }
2. 打包前,在指定的类型声明文件中采用三斜线指令引入命名文件 feature.d.ts
/// <reference types="./typings/feature" />
随手纪录,希望能帮到正在被此问题困扰的你。