typescript - 如何正确要求 typescript 中依赖项的类型?
问题描述
我有一个关于在我的项目中解析类型的问题。所以基本上我有packageA -> packageB-v1 -> packageC-v1
,我想使用在 inside 中声明的packageC-v1
类型packageA
。
所有包都是我自己创建的,都是typescript包,通过declaration: true
在文件中设置生成声明文件tsconfig.json
,它们每个都暴露*.d.ts
在他们的dist
文件夹中的多个文件。类型没有对应@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 将安装packageC-v2
而不是packageC-v1
underpackageB/node_modules
。SomeType
首先从packageB-v1
by中导出必要的类型export SomeType from 'packageC-v1'
,然后从 packageA 中导出即可import SomeType from 'packageB-v1'
。这也有效,但是,这也意味着要从其消费者可能需要的所有依赖项(可能有很多依赖项)packageB-v1
中重新导出所有类型。这通常是不可能的。另外,我听说再导出可能会产生不同的类型,具体取决于每种情况。- 在
packageA
'spackage.json
文件中,packageC-v1
显式添加依赖,即使它实际上并不直接依赖它。所以我们可以使用import SomeType from 'packageC-v1/SomeType
. 不幸的是,这也不起作用,因为我们可能有另一个依赖链,例如packageA -> packageD-v1 -> packageC-v2
. 在那种情况下,packageC
我们应该在哪个版本下安装packageA
?这种方法也很糟糕,因为即使 typescript 实际上不会包含packageC
在生成的 JS 包中,packageA
仅用于使用接口,它可能会为枚举执行此操作。
我没有尝试的最后一种方法是创建我自己的@types/packageC-v1
并发布它(以及我的其他 ts 包)。但是,如果我为私有组织编写这些包,这意味着我们需要维护一个内部类型存储库,以及维护与它们关联的包和类型的配对版本。即使我设法做到了,我仍然可以看到这种方法在版本不匹配、全局声明冲突或名称范围冲突方面存在许多问题(在该DefinetelyTyped/types
方法中也是如此)。
我不确定这些对您是否有意义,并且在这里确实需要一些建议。
解决方案
让我们从一个琐碎的事情开始:如果一个包A
需要来自 package 的东西C
,那么C
根据定义是A
.
你说你有理由不包括C
在依赖项中A
我们可能有另一个依赖链,比如 packageA -> packageD-v1 -> packageC-v2
在这种情况下,如果A
使用来自C-v1
的类型,这应该如何工作?我只能看到两种可能性:
A
C
使用时不需要类型packageD
。(顺便说一句,为什么它需要C
使用类型packageB
呢?)C
类型没有改变,所以C
类型 fromC-v1
兼容C-v2
对于#1 和#2,我能看到的唯一解决方案是将类型从C
单独的包中拆分出来,例如 C-types
,并使其成为A
.
中的类型不C-types
应该是 TypeScript 生成的文件,这些应该是所有接口、类型和枚举(但不是类,类是实现细节,应该保留在 中),移出到包含在单独包中的常规文件中。d.ts
C
C
.ts
对于每个版本的. C-types
_ 我不认为有空文件是一个问题,但如果是这样,你可以发布手动编写的文件(但是我不知道在发布之前对它们进行类型检查,而没有另一个包使用它们)。无需通过DefinedTyped发布并将它们包含在范围内 - 这只是一个约定,而不是要求。您只需要告诉组织中的每个人使用而不是.C
.d.ts
.js
C
.js
.d.ts
C-types
@types
C-types
@types/C
你说用这种方法
在版本不匹配、全局声明冲突或名称范围冲突方面,我仍然可以看到这种方法的许多问题(在 DefinetelyTyped/types 方法中也是如此)
首先,强烈建议不要使用全局声明——模块的发明是有原因的,在任何地方使用的每个名称都应该从某个地方显式导入。
如果您A
使用来自 的类型C
,那么使用不同版本的C
. 拆分类型C
只会让您事先考虑这些问题,而不是希望事情会“正常工作”。
推荐阅读
- reactjs - 在ajax调用后反应更新dom模板
- javascript - 基于用户输入的 JavaScript 字体颜色变化
- python - Pandas:如果无序,则跨列对 DataFrame 单元格进行排序
- java - JDK11 HttpClient 双向 tls
- php - Laravel 5.8 Class XXX 注入时不存在
- javascript - TypeORM 中的 OneToMany 关系在哪里
- react-native - React Native 自动导航到另一个屏幕
- mysql - 如何在浏览器界面内完成未实现的 SQL 查询?
- java - 在 Spring Boot/JPA 查询语言中实现复杂的 MAX 函数
- itemtemplate - Visual Studio ItemTemplate 共享参数