在同构 Typescript 库中引用特定于平台的类型的正确方法

Cod*_*rer 13 node.js typescript isomorphic-javascript

我正在尝试编写一个 Typescript 库,我希望能够在针对浏览器和 Node.js 时包含该库。我有两个问题:在代码主体中引用特定于平台的类型,以及将这些类型包含在.d.ts伴随转译的 JS 生成的声明中。

在第一种情况下,我想写一些类似的东西

  if (typeof window === "undefined") {
    // Do some Node-y fallback thing
  } else {
    // Do something with `window`
  }
Run Code Online (Sandbox Code Playgroud)

如果我不包含"dom"lib编译器选项中(也就是说,如果我只是说lib: ["es2016"]in ),则编译失败,因为未定义tsconfig全局。window(Usingwindow只是 out of 的一个示例lib.dom.d.ts,也可能是fetchor a ResponseorBlob等​​。)重点是,通过在使用全局对象之前检查全局对象是否存在,代码在运行时应该是安全的,它是类型我无法弄清楚的一面。

在第二种情况下,我在构建库后尝试包含该库时遇到错误。"dom"我可以使用in选项构建库lib,并且生成的输出包括带有例如的键入declare export function foo(x: string | Blob): void。问题是,如果使用的代码不包含Blob(无"dom"库)的定义,则它无法编译,即使它实际上只是使用fooa进行调用string(或foo根本不使用!)。

如果我可以帮助的话,我不希望我的库(或消费者)尝试用伪造window或声明污染全局名称空间。Blob更多的等距库不断涌现,但我还没有找到一个好的 Typescript 示例可供参考。(如果这个主题对于 SO 来说太复杂,我仍然非常感谢指向文档或文章/博客文章的指针。)

Say*_*Pal 0

我认为这是一个典型的抽象案例,也是一个简单的案例。也就是说,您针对IPlatform接口进行编码并在代码中引用该接口。该接口又隐藏了所有特定于平台的实现。

您还可以另外公开 API,以便消费者通常可以使用适当的“全局”对象轻松初始化“平台”。使用依赖注入将正确的(特定于平台的)实例注入IPlatform到您的代码中。这应该会严重减少代码中的分支并使代码保持干净。正如您在问题中指出的那样,您不必使用这种方法用虚假声明来污染您的代码。

或者,您还可以IPlatform从包中导出实例,以便消费者也可以从中受益。

你提到的第二个问题:

问题是,如果使用的代码不包含 Blob 的定义(没有“dom”lib),则它无法编译,即使它实际上只是使用字符串调用 foo(或者根本不使用 foo!)。

@types/node我认为通过在消费者端安装为 devDependency 可以轻松解决这个问题。这应该具有相对较低的占地面积,因为这不会增加消费者的捆绑。