如何从打字稿中的依赖项中正确要求类型?

时间:2019-02-03 18:48:41

标签: typescript npm dependencies yarnpkg

我有一个关于解决项目中类型的问题。所以基本上我有packageA -> packageB-v1 -> packageC-v1,并且我想使用packageC-v1packageA中声明的类型。

所有软件包都是由我自己创建的,并且都是打字稿软件包,它们通过在declaration: true文件中设置tsconfig.json来生成声明文件,它们各自在{{1 }}文件夹。类型没有相应的*.d.ts包。

在这种情况下,如何正确导入类型?到目前为止,我已经尝试过:

  1. dist。此方法有效,但我不喜欢@types/*需要知道import SomeType from 'packageB-v1/node_modules/packageC-v1/dist/SomeType'的安装位置,因为它可能会更改,具体取决于软件包管理工具(npm / yarn)或安装顺序(请参阅{{3 }})。我看到的问题是,由于packageA的版本不同,类型不同并且packageC对此并不满意。当存在诸如packageC之类的另一个依赖项时,可能会发生这种情况,其中npm将安装tsc而不是packageA -> packageB-v1 -> packageBB-v1 -> packageC-v2下的packageC-v2
  2. 首先通过packageC-v1packageB/node_modules导出必要的类型SomeType,然后从packageA中导出packageB-v1。这也可行,但是,这还意味着export SomeType from 'packageC-v1'可以从 all 依赖项中重新导出 all 类型(可能有很多) )其消费者可能可能需要。通常这是不可能的。另外,我听说转口可能会根据情况而产生不同的类型。
  3. import SomeType from 'packageB-v1'的{​​{1}}文件中,将依赖项显式添加到packageB-v1中,即使实际上并不直接依赖于此。因此我们可以使用packageA。不幸的是,这也不起作用,因为我们可能还有另一个依赖链,例如package.json。在那种情况下,我们应该在packageC-v1下安装哪个import SomeType from 'packageC-v1/SomeType版本?这种方法也是不好的,因为即使打字稿实际上不会将packageA -> packageD-v1 -> packageC-v2生成的JS包中包含packageC仅用于使用接口,它也可能会为枚举使用。

我最后没有尝试的方法是创建自己的packageA并将其发布(以及其他ts包)。但是,如果我为私人组织编写这些软件包,则意味着我们需要维护一个内部类型存储库,以及维护成对的软件包和与之关联的类型。即使我设法做到了这一点,我仍然可以从版本不匹配,全局声明冲突或名称范围冲突(在packageC方法中也是如此)中看到这种方法的许多问题。

我不确定这些对您是否有意义,真的需要一些建议。

1 个答案:

答案 0 :(得分:1)

让我们从一个简单的例子开始:如果一个软件包A需要来自软件包C的东西,那么C的定义就是A的直接依赖。

您说您有理由不将C的依赖项中包含A

  

我们可能还有另一个依赖链,例如packageA-> packageD-v1->   packageC-v2

在这种情况下,如果A使用C-v1中的类型,这应该如何工作?我只能看到两种可能性:

    使用A时,
  1. C不需要packageD中的类型。 (顺便说一句,为什么它需要C类型才能使用packageB?)

  2. C类型没有更改,因此C中的C-v1类型与C-v2

  3. 兼容

我对#1和#2唯一看到的解决方案是将C中的类型拆分为单独的包,例如C-types,并使其成为{{1}的dev依赖项}。

A中的类型应该不是是TypeScript生成的C-types文件,它们应该是所有接口,类型和枚举(但不是类,类是实施细节,并且应保留在d.ts的{​​{1}}中,移到单独软件包中包含的常规C文件中。

对于每个版本的{,您必须以与发布C相同的方式在npm存储库中发布.ts,其中包含生成的C-types和空的C文件{1}}。我认为没有空的.d.ts文件不是问题,但是如果是这样,您可以发布手动编写的.js文件(但是我不知道在发布之前进行类型检查,而没有使用另一个软件包)。无需发布CDefinitelyTyped并将它们放到.js范围内-这只是一个约定,不是必需的。您只需要告诉组织中的每个人都使用.d.ts而不是C-types

您说的是这种方式

  

就版本而言,我仍然可以看到这种方法的许多问题   不匹配,全局声明冲突或名称范围冲突(这是   在DefinetelyTyped / types方法中也是如此)

首先,强烈建议不要使用全局声明-出于某种原因发明了模块,应该在任何地方显式导入每个地方使用的每个名称。

如果您的@types使用C-types中的类型,则使用不同版本的@types/C的版本问题将完全相同。从A中分离类型只会让您事先考虑这些问题,而不是希望事情会“正常”。