使用INFER和TYPEOF在打印脚本中创建工厂 [英] Creating a Factory in Typescript using infer and typeof
问题描述
主要目标: 我正在努力学习(并理解,而不仅仅是复制和粘贴)如何在TypeScrip中创建一个Factory,但我对类型和类型推断有几点困惑。我想 使类能够创建ICLonable的多个实例(&Q;MyCloner&Q;;)例如,如果我有一个卡车类和一个摩托车类,这两个类都实现了ICLonable。
我希望能够做到以下几点:
const vehicleCloner = new MyCloner();
const truck = new Truck({color: 'red', fuel: 'electric'});
和MyClone执行如下操作:
var myTenElectricTrucks = vehicleCloner.cloneWithRandomColors(truck, 10);
第一个混淆点(推断和新的): 我一直在遵循一些教程,但我不完全理解这些:
type ExtractInstanceType<T> = T extends new () => infer R ? R : never;
我想我不习惯在一切都在进行的情况下声明类型。我知道我们声明了某种类型,看起来能够接受一个名为T的泛型。然后,看起来T正在扩展函数&new&q;(据我所知,这是一个保留的关键字)。但是,R、T和‘new’之间有什么关系呢?我不明白这里的=>;运算符是怎么回事(它是用来声明函数的吗?)
我不确定在查找TypeScrip后是否理解了Infer在TypeScrip中的作用。
这里是 the tutorial for ExtractInstanceType和上下文
我意识到让卡车保持电动是额外的,据我所知通常不是工厂模式的一部分,但这是最终的目标。但我认为,在理解了Infer和ExtractInstanceType的基础知识后,这应该不会是很大的一步。
感谢您抽出时间。
第二点混淆(更多类型声明和类型文字):
我也被the same tutorial中的以下一行搞糊涂了。
type userTypes = typeof userMap[Keys]; //typeof Developer | typeof Manager
对我来说,这看起来像是在说Keys不是单个密钥?通常在JS中,我希望它是一个字符串,它从字典中返回一个值?但键本质上是表示多个类型的类型文字,然后以某种方式用作单个键?
以下是供参考的关键字:
type Keys = keyof typeof userMap; // 'dev' | 'manager'
推荐答案
以后尝试将自己限制为每个问题只能回答一个问题,但您的问题的答案非常简洁,因此...
让我们将条件类型声明转换为一些伪代码,以便更清楚地指示发生了什么:
type InstanceType(T)=如果T是一个类则通过
new
构造的对象的类型否则类型never
让我们逐渐回到实际的代码(这些都是同一事物的表示):
type InstanceType<T> = (T is a class) ? (thing-T-constructs, i.e. 'R') : never
type InstanceType<T> = (T extends (new () => R)) ? R : never
希望逐行查看替换(就像简化数学中的公式)会有所帮助。T extends new () => R
只是表示‘T满足new
能够返回R
的对象’的约束,R
只是‘类T
构造的对象’。never
只是作为一种保护措施:以防调用方错误地将类型与非类泛型参数一起使用。
现在我们有了语法上几乎有效的打字稿。但问题是R
:它是一个未声明的变量,在类型中和在代码中一样有问题。这就是infer
关键字的用武之地:
type InstanceType<T> = (T extends (new () => infer R)) ? R : never
// and dropping the grouping parens to arrive back at the original:
type InstanceType<T> = T extends new () => infer R ? R : never
这里我们告诉编译器根据所满足的条件推断R
的类型,即T
是可以用new
构造的类。注意:AFAIKinfer
只能用于这样的条件类型上下文。
type Keys = keyof typeof userMap;
这里,我们希望基于值userMap
中的键构造类型。由于我们不能将值用作类型,因此必须调用typeof
来获取用户映射的类型,并且由于它是一个关联数据结构,因此可以调用keyof
来获取映射键的并集:'dev' | 'manager'
。
然后,我们可以使用索引类型从映射中获得值的类型的并集(在键/值对意义上):
type userTypes = typeof userMap[Keys];
您可能认为是Developer | Manager
,但由于我们构造的是类型(userTypes
),并且不能使用值作为类型,因此实际的联合是typeof Developer | typeof Manager
。
所以总结一下第二部分:
typeof userMap; // Typescript compile-time type of the userMap
keyof typeof userMap; // The type of the *compile-time keys* of userMap
typeof userMap[keyof typeof userMap] // ditto but for the types of the *values* in the map
这篇关于使用INFER和TYPEOF在打印脚本中创建工厂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!