如何正确地从打字稿中的依赖项中获取类型?
How to correctly require types from dependencies in typescript?
我对解决项目中的类型有疑问。所以基本上我有 packageA -> packageB-v1 -> packageC-v1
,我想在 packageA
.
中使用 packageC-v1
中声明的类型
所有包都是我自己创建的,都是通过在tsconfig.json
文件中设置declaration: true
来生成声明文件的typescript包,它们各自在自己的[中暴露多个*.d.ts
文件=16=]文件夹。类型没有相应的 @types/*
包。
这种情况下,应该如何正确导入类型呢?到目前为止我已经尝试过:
import SomeType from 'packageB-v1/node_modules/packageC-v1/dist/SomeType'
。这行得通,但我不喜欢 packageA
需要知道 packageC
的安装位置,因为它可能会根据包管理工具(npm/yarn)或安装顺序(见 https://medium.com/learnwithrahul/understanding-npm-dependency-resolution-84a24180901b).我已经看到由于 packageC
的不同版本,类型不一样并且 tsc
不合适的问题。当有另一个依赖项如 packageA -> packageB-v1 -> packageBB-v1 -> packageC-v2
时,可能会发生这种情况,npm 将在 packageB/node_modules
. 下安装 packageC-v2
而不是 packageC-v1
- 首先通过
export SomeType from 'packageC-v1'
从 packageB-v1
导出必要的类型 SomeType
,然后从 packageA 我可以 import SomeType from 'packageB-v1'
。这也有效,但是,这也意味着 packageB-v1
无法从其依赖项的 all 中重新导出 all 类型(可能有很多)它的消费者可能需要。这通常是不可能的。另外,我听说再导出可能会生成不同的类型,具体取决于每种情况。
- 在
packageA
的package.json
文件中,显式添加对packageC-v1
的依赖,即使它实际上并不直接依赖它。所以我们可以使用 import SomeType from 'packageC-v1/SomeType
。不幸的是,这也行不通,因为我们可能有另一个依赖链,如 packageA -> packageD-v1 -> packageC-v2
。在那种情况下,我们应该在 packageA
下安装哪个 packageC
版本?这种方法也很糟糕,因为即使打字稿实际上不会在从 packageA
生成的 JS 包中包含 packageC
仅用于使用接口,它可能会为枚举这样做。
我没有尝试过的最后一种方法是创建我自己的 @types/packageC-v1
并发布它(以及我的其他 ts 包)。但是,如果我为私人组织编写这些包,这意味着我们需要维护一个内部类型存储库,以及维护包的配对版本和与之关联的类型。即使我设法做到了这一点,我仍然可以看到这种方法在版本不匹配、全局声明冲突或名称范围冲突方面的许多问题(在 DefinetelyTyped/types
方法中也是如此)。
我不确定这些对你是否有意义,这里真的需要一些建议。
让我们从一个琐碎的事情开始:如果包 A
需要包 C
中的某些东西,那么根据定义 C
是 A
的直接依赖项。
您说您有理由不将 C
包含在 A
的依赖项中
we may have another dependency chain like packageA -> packageD-v1 ->
packageC-v2
在这种情况下,如果 A
使用来自 C-v1
的类型,这应该如何工作?我只能看到两种可能性:
A
在使用 packageD
时不需要来自 C
的类型。 (顺便说一下,为什么它需要 C
类型来使用 packageB
呢?)
C
类型没有改变,因此 C-v1
中的 C
类型与 C-v2
[=79= 兼容]
对于#1 和#2,我能看到的唯一解决方案是将 C
中的类型拆分到单独的包中,例如 C-types
,并使其成为 [= 的开发依赖项10=]。
C-types
中的类型应该不是由TypeScript生成的d.ts
文件,这些应该是所有接口、类型和枚举(但不是类、类 是一个实现细节,应该保留在 C
) 从 C
中移出到包含在单独包中的常规 .ts
文件中。
您必须以与发布 C
相同的方式在 npm 存储库中发布 C-types
,为每个版本生成 .d.ts
和空 .js
文件C
个。我不认为有空的 .js
文件是个问题,但如果是的话,你可以只发布手动编写的 .d.ts
文件(但是我不知道在发布之前对它们进行类型检查,没有有另一个包使用它们)。没有必要通过 DefinitelyTyped 发布 C-types
并将它们放在 @types
范围内——这只是一个约定,而不是要求。您只需告诉组织中的每个人使用 C-types
而不是 @types/C
.
你说用这个方法
I can still see many issues with this approach in terms of version
mismatch, global declaration conflict, or namescope conflict (it is
also true in the DefinetelyTyped/types approach)
首先,强烈建议不要使用全局声明 - 模块的发明是有原因的,在任何地方使用的每个名称都应该从某个地方明确导入。
并且如果您的 A
使用来自 C
的类型,您将在使用不同版本的 C
时遇到完全相同的版本控制问题。从 C
中拆分类型只会让你事先考虑这些问题,而不是希望事情会 "just work".
我对解决项目中的类型有疑问。所以基本上我有 packageA -> packageB-v1 -> packageC-v1
,我想在 packageA
.
packageC-v1
中声明的类型
所有包都是我自己创建的,都是通过在tsconfig.json
文件中设置declaration: true
来生成声明文件的typescript包,它们各自在自己的[中暴露多个*.d.ts
文件=16=]文件夹。类型没有相应的 @types/*
包。
这种情况下,应该如何正确导入类型呢?到目前为止我已经尝试过:
import SomeType from 'packageB-v1/node_modules/packageC-v1/dist/SomeType'
。这行得通,但我不喜欢packageA
需要知道packageC
的安装位置,因为它可能会根据包管理工具(npm/yarn)或安装顺序(见 https://medium.com/learnwithrahul/understanding-npm-dependency-resolution-84a24180901b).我已经看到由于packageC
的不同版本,类型不一样并且tsc
不合适的问题。当有另一个依赖项如packageA -> packageB-v1 -> packageBB-v1 -> packageC-v2
时,可能会发生这种情况,npm 将在packageB/node_modules
. 下安装 - 首先通过
export SomeType from 'packageC-v1'
从packageB-v1
导出必要的类型SomeType
,然后从 packageA 我可以import SomeType from 'packageB-v1'
。这也有效,但是,这也意味着packageB-v1
无法从其依赖项的 all 中重新导出 all 类型(可能有很多)它的消费者可能需要。这通常是不可能的。另外,我听说再导出可能会生成不同的类型,具体取决于每种情况。 - 在
packageA
的package.json
文件中,显式添加对packageC-v1
的依赖,即使它实际上并不直接依赖它。所以我们可以使用import SomeType from 'packageC-v1/SomeType
。不幸的是,这也行不通,因为我们可能有另一个依赖链,如packageA -> packageD-v1 -> packageC-v2
。在那种情况下,我们应该在packageA
下安装哪个packageC
版本?这种方法也很糟糕,因为即使打字稿实际上不会在从packageA
生成的 JS 包中包含packageC
仅用于使用接口,它可能会为枚举这样做。
packageC-v2
而不是 packageC-v1
我没有尝试过的最后一种方法是创建我自己的 @types/packageC-v1
并发布它(以及我的其他 ts 包)。但是,如果我为私人组织编写这些包,这意味着我们需要维护一个内部类型存储库,以及维护包的配对版本和与之关联的类型。即使我设法做到了这一点,我仍然可以看到这种方法在版本不匹配、全局声明冲突或名称范围冲突方面的许多问题(在 DefinetelyTyped/types
方法中也是如此)。
我不确定这些对你是否有意义,这里真的需要一些建议。
让我们从一个琐碎的事情开始:如果包 A
需要包 C
中的某些东西,那么根据定义 C
是 A
的直接依赖项。
您说您有理由不将 C
包含在 A
we may have another dependency chain like packageA -> packageD-v1 -> packageC-v2
在这种情况下,如果 A
使用来自 C-v1
的类型,这应该如何工作?我只能看到两种可能性:
A
在使用packageD
时不需要来自C
的类型。 (顺便说一下,为什么它需要C
类型来使用packageB
呢?)
[=79= 兼容]C
类型没有改变,因此C-v1
中的C
类型与C-v2
对于#1 和#2,我能看到的唯一解决方案是将 C
中的类型拆分到单独的包中,例如 C-types
,并使其成为 [= 的开发依赖项10=]。
C-types
中的类型应该不是由TypeScript生成的d.ts
文件,这些应该是所有接口、类型和枚举(但不是类、类 是一个实现细节,应该保留在 C
) 从 C
中移出到包含在单独包中的常规 .ts
文件中。
您必须以与发布 C
相同的方式在 npm 存储库中发布 C-types
,为每个版本生成 .d.ts
和空 .js
文件C
个。我不认为有空的 .js
文件是个问题,但如果是的话,你可以只发布手动编写的 .d.ts
文件(但是我不知道在发布之前对它们进行类型检查,没有有另一个包使用它们)。没有必要通过 DefinitelyTyped 发布 C-types
并将它们放在 @types
范围内——这只是一个约定,而不是要求。您只需告诉组织中的每个人使用 C-types
而不是 @types/C
.
你说用这个方法
I can still see many issues with this approach in terms of version mismatch, global declaration conflict, or namescope conflict (it is also true in the DefinetelyTyped/types approach)
首先,强烈建议不要使用全局声明 - 模块的发明是有原因的,在任何地方使用的每个名称都应该从某个地方明确导入。
并且如果您的 A
使用来自 C
的类型,您将在使用不同版本的 C
时遇到完全相同的版本控制问题。从 C
中拆分类型只会让你事先考虑这些问题,而不是希望事情会 "just work".