为什么要在DefinitelyTyped上为Javascript库发布TypeScript声明文件?

ber*_*nie 7 javascript npm typescript definitelytyped typescript-typings

我在npm上发布了两个Javascript库,并且用户要求为它们两者都提供TypeScript类型定义。我自己不使用TypeScript,也没有计划用TypeScript重写这些库,但是我仍然想添加类型定义文件,如果只是为了更好地完成IntelliSense代码。我正在寻找一些建议。

我首先阅读了DefinitelyTyped项目的文档以及有关发布npm包的声明文件的文档。两个来源都指出“对于不在TypeScript中编写的项目,首选方法是在npm上发布到@types组织”。

为什么相比通过库中的types字段将类型定义与库本身一起发布,它为什么更受青睐package.json?我真的看不到让第三方参与其中的意义。似乎更新类型定义并对其进行版本控制更加复杂。

以上引用的文档中的引号(重点是我的)

来自DefinitelyTyped:

如果您是库作者,并且您的包是用TypeScript编写的,则将自动生成的声明文件捆绑在您的包中,而不是发布为“确定类型”。

来自typescriptlang.org:

既然您已经按照本指南的步骤编写了声明文件,那么现在该将其发布到npm了。可以将声明文件发布到npm的主要方法有两种:

  • 与您的npm软件包捆绑在一起,或者
  • 在npm上发布到@types组织。

如果您的程序包是用TypeScript编写的,首选第一种方法。使用--declaration标志生成声明文件。这样,您的声明和JavaScript将始终保持同步。

如果您的软件包不是用TypeScript编写的,第二种方法是首选方法。

两者似乎都说:

if (isAuthor && lang === "typescript")
  bundle();
else
  publishOnDefinitelyTyped();
Run Code Online (Sandbox Code Playgroud)

小智 8

类型声明发布指南在多个领域似乎有点过时且稀疏。

\n

我将尝试详细比较这两种情况。

\n

1. 与 npm 包捆绑在一起的类型

\n

1.1. 从包装消费者角度

\n

1.1.1. 优点

\n

一般来说,由于简化的依赖管理,包捆绑类型更加方便。

\n
    \n
  • 不需要额外的@types依赖(添加包依赖)
  • \n
  • 无需在包及其类型之间同步版本(升级包依赖项)
  • \n
\n

1.1.2. 缺点

\n
    \n
  • 选择不使用包捆绑类型的有限方法

    \n

    涉及消费者需要修改或替换类型声明的情况。

    \n

    由于配置选项已经有限,在具有固执己见的构建设置的项目中,该过程可能会出现相当大的问题。

    \n
  • \n
\n

1.2. 从包作者的角度来看

\n

1.2.1. 优点

\n
    \n
  • 库所有者可以按照自己的意愿、以任何频率或时间表发布补丁和类型声明的更新
  • \n
  • 对第三方或外部类型依赖性没有限制
  • \n
  • 为多个版本提供并发支持的方式与实际代码相同
  • \n
\n

1.2.2. 缺点

\n

将类型与包捆绑在一起意味着每次发布版本时实际上都会发布两个 API 合约。

\n

例子:

\n

让我们假设一个旨在符合 semver 版本控制的库。

\n
    \n
  • 最新版本 -> 1.0.0
  • \n
  • 主要版本由于重大更改而被提升 -> 2.0.0
  • \n
  • 报告了类型声明中的一个严重错误,对于具有打字稿项目的一组用户来说,该版本已被破坏
  • \n
  • 类型的修复是一个重大改变
  • \n
\n

下一个版本的选项有:

\n

A.2.XX -> 违反类型声明的 semver 规则

\n

B.3.0.0 -> 违反了实际代码的 semver 规则

\n

这种情况可能有多种变化。

\n

2. 发布到明确类型的存储库

\n

2.1. 从包装消费者角度

\n

2.1.1. 优点

\n
    \n
  • 通过删除@types依赖来简单选择退出
  • \n
\n

2.1.2. 缺点

\n
    \n
  • 包使用者有责任保持包和相关类型版本同步
  • \n
\n

2.2. 从包作者的角度来看

\n

2.2.1. 优点

\n
    \n
  • 类型对包的发布周期没有影响

    \n
  • \n
  • DT repo 有两个额外的特征:

    \n
      \n
    • 用于类型断言和类型测试的 dts-lint 库
    • \n
    • 深入的性能和编译器占用分析,包括最新包版本和 PR 修改后的包之间的差异。
    • \n
    \n

    第一个工具可以轻松地合并到另一个包存储库中。\n我不确定分析是否可以复制到自己的存储库中,但它包含大量有价值的数据。

    \n
  • \n
\n

2.2.2. 缺点

\n
    \n
  • 支持过去版本的非标准方式

    \n
  • \n
  • 受 DT 审核和发布周期限制的类型发布时间表

    \n

    假设 DefinelyTyped PR 创建者是 @types 包所有者,则合并 PR 通常需要一到两天的时间。此外,在 types-publisher 更新 PR 相关的 @types npm 包之前,会有轻微的延迟。

    \n

    当 PR 是作者对给定包的第一个贡献时,会涉及额外的审核过程。

    \n
  • \n
  • 使用外部依赖项

    \n

    TypeScript 手册说:

    \n
    \n

    如果您的类型定义依赖于另一个包:

    \n

    不要将\xe2\x80\x99 与你的结合起来,将每个文件保存在自己的文件中。

    \n

    也不要复制包中的声明。

    \n

    如果 npm 类型声明包未打包其声明文件,请务必依赖它。

    \n
    \n

    从冗余实用程序类型的数量来看,这些功能很难得到尊重。

    \n

    类型声明的作者可以使用相邻的 DT 存储库类型。\n依赖于此列表之外的包,要求它们位于类型发布者白名单中。

    \n

    可以通过向 types-publisher 提交 PR 将新包列入白名单。\n我的 PR 花了两周多的时间才被合并。我不知道这是否常见,因为我已经提交了一份 PR。

    \n
  • \n
  • DT 回购量

    \n

    我没有跨 IDE 的比较或经验,但就 JetBrains IDE 而言,完全索引的 DT repo 项目的内存占用导致 IDE 无法使用。

    \n

    禁用对更改的重新编译在一定程度上有所帮助。可以通过删除与感兴趣的包不相关的 DT 存储库内容来解决令人沮丧的 IDE 体验。

    \n
  • \n
\n