使用INFER和TYPEOF在打印脚本中创建工厂 [英] Creating a Factory in Typescript using infer and typeof

查看:13
本文介绍了使用INFER和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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆