带有环境 d.ts 模块的 Typescript ES6 模块语法

Typescript ES6 module syntax with ambient d.ts module

假设我有一个包含 50 个文件的模块,每个模块都包含:

export class <SomeClassName> { /* content */ }

然后,我创建了一个根文件以通过重新导出所有文件来简化使用。所以它看起来像:

export * from "./src/some-class-1";
export * from "./src/some-class-2";
export * from "./src/some-class-3";
// etc

然后,我 运行 它通过 TSC 做一个 "common" 模块目标 "es5" 与描述符输出。

到目前为止一切顺利。我有我的 package.json 名称 my-module 目标输出 index.js 作为我的模块的入口点。所以我现在决定在另一个打字稿项目中使用这个模块。

所以我为它安装了 npm(让我们假装)npm install my-module 并且它全部引入,所以我现在有生成的 d.ts 文件,我有实际的 commonjs 模块所以我可以全部使用。一切似乎都很好。

那么问题来了。然后我决定使用模块:

import {SomeClass1} from 'my-module'

在TS的世界里炸了,不知道my-module是什么东西,好像我们回过头来看输出的index.js,不包含环境模块。

所以问题来了,普通模块在包含模块名时一般使用package.json作为参考点,而TS使用d.ts文件。所以我想好吧,我需要将我的重新导出包装在 index.ts 中的一个模块中,所以我尝试:

export module "my-module" { /* all other re-exports */ }

但事实证明你只能为环境模块使用字符串模块名称,并且你只能将它们放在 d.ts 文件中,但是我的 d.ts 文件是从现有代码库生成的。

所以这是我的困境,我可以手动进入并向我的 d.ts 添加一个 declare module "my-module 包装器,但它不是很自动化,或者我喜欢使用 ES6 语法的博客文章并相对地引用文件,最终会有很多 import {blah} from "../node_modules/my-module/dist/index",希望我们都同意这有点愚蠢。

所以我找不到任何其他适用于自动化世界的方法,因为当您使用 ES6 语法时,所有关于这个主题的博客文章和文档都使用相对文件导入,而不是从 when 整个事情导入已通过 d.ts 个文件编译和共享。

那么这里有没有办法用文本模块名称包装我的重新导出?或者至少告诉 index.d.ts 包含在环境模块中? (请记住,它会为项目中的每个文件输出一个 d.ts 文件,但我们只关心通过索引导入模块。d.ts 因为它会重新导出所有内容)。

当你编译index.ts时,你需要告诉TSC为你生成定义文件。

index.ts:

export * from "./src/some-class-1";
export * from "./src/some-class-2";
export * from "./src/some-class-3";

命令:

tsc --declaration index.ts

这应该为索引生成一个 d.ts 文件,其中包含导出以及每个 some-class-* 及其导出的 d.ts

当然,用户需要参考所有 d.ts 文件才能使其正常工作,目前是 PITA;参见 this。我相信您可以使用 --out 选项将所有文件合并为一个文件,其中包括 d.ts。不过,我也不确定那是你想要的。

现在您仍然需要使用另一个工具来为您的包生成单个 .d.ts 文件。有一些工具可以做到这一点:

我个人使用 customized version of dts-generator that makes use of tsconfig.json and works with nightly TypeScript builds. You can see a .d.ts that it generated for one of my packages over here

好的,我终于让它工作了,至少对于 CommonJS 来说是这样。

现在随着 typescript 1.6 的变化,TS 模块分辨率将检查 node_modules 文件夹中的 index.d.ts 文件。所以我基本上在构建过程结束时添加了这个文件,它指向我的 dist/definitions/index.d.ts 文件,其中包含所有导出。

通过这种方式,您可以像 import * from "my-module" 这样进行导入,只要在您的 node_modules 文件夹中有一个带有 index.d.tsmy-module 文件夹,它基本上会处理该索引中的所有内容都作为一个模块。

如果其他人得到更好的解决方案,适用于所有人而不仅仅是 commonjs,我会很乐意将答案更改为另一个,但目前它足以让我继续前进,希望它可以帮助其他人。