typescript - 将 TypeScript 的 InstanceType 泛型与抽象类一起使用?
问题描述
TypeScript 2.8 添加了一个新的核心类型InstanceType
,可用于获取构造函数的返回类型。
/**
* Obtain the return type of a constructor function type
*/
type InstanceType<T extends new (...args: any[]) => any> = T extends new (...args: any[]) => infer R ? R : any;
这个特性非常好,但是在使用抽象类时就崩溃了,抽象类没有new
根据 TypeScript 的类型系统的声明。
起初,我认为我可以通过创建一个类似但限制较少的类型(移除extends new (...args: any[]) => any
保护)来绕过这个限制:
export type InstanceofType<T> = T extends new(...args: any[]) => infer R ? R : any;
但是当传递一个抽象类时它也崩溃了,因为它无法推断返回类型并且默认为any
. 这是一个使用模拟 DOM 作为示例的示例,尝试进行类型转换。
abstract class DOMNode extends Object {
public static readonly TYPE: string;
constructor() { super(); }
public get type() {
return (this.constructor as typeof DOMNode).TYPE;
}
}
class DOMText extends DOMNode {
public static readonly TYPE = 'text';
constructor() { super(); }
}
abstract class DOMElement extends DOMNode {
public static readonly TYPE = 'text';
public static readonly TAGNAME: string;
constructor() { super(); }
public get tagname() {
return (this.constructor as typeof DOMElement).TAGNAME;
}
}
class DOMElementDiv extends DOMElement {
public static readonly TAGNAME = 'div';
constructor() { super(); }
}
class DOMElementCanvas extends DOMElement {
public static readonly TAGNAME = 'canvas';
constructor() { super(); }
}
// Create a collection, which also discards specific types.
const nodes = [
new DOMElementCanvas(),
new DOMText(),
new DOMElementDiv(),
new DOMText()
];
function castNode<C extends typeof DOMNode>(instance: DOMNode, Constructor: C): InstanceofType<C> | null {
if (instance.type !== Constructor.TYPE) {
return null;
}
return instance as InstanceofType<C>;
}
// Attempt to cast the first one to an element or null.
// This gets a type of any:
const element = castNode(nodes[0], DOMElement);
console.log(element);
如果该构造函数是抽象类,有什么方法可以将变量转换为传递的构造函数的实例?
注意:我试图避免使用instanceof
,因为 JavaScriptinstaceof
非常有问题(同一模块的 2 个不同版本具有不同的构造函数实例)。
解决方案
您可以查询prototype
抽象class
的类型以获取其实例的类型。这并不要求该类型具有new
签名,只要求它具有prototype
属性。抽象类没有new
签名,但它们确实有一个prototype
属性。
这是它的样子
function castNode<C extends typeof DOMNode>(
instance: DOMNode,
Constructor: C
): C['prototype'] | null {
if (instance.type !== Constructor.TYPE) {
return null;
}
return instance;
}
类型位置中的表达式C['P']
称为索引访问类型。它是 type 中命名的属性值P
的类型 C
。
推荐阅读
- node.js - 在 node.js 上通过 Mongoose 连接到 MongoDB Atlas 的问题
- haskell - 制作 Applicative 的实例
- android - Nativescript如何在后台发出http请求
- python - 如何在 PyTorch 中加载具有多个 JSON 注释的图像
- maven - VSCode - Maven.archetype.generate 失败
- android - Android Studio 看起来不合适
- php - 使用 Xdebug 和 PhpStorm 找不到 Symfony ContainerAwareCommand
- mysql - MySQL - 如何选择日期时间字段不等于 0000-00-00 00:00:00 的行?
- mysql - MySQL XAMPP 总是打开一个网络命令弹出窗口
- r - 在地图函数中使用条件改变多个列