使用泛型和构造函数的TypeScript强制转换类型? [英] TypeScript cast type using generics and constructor?

查看:87
本文介绍了使用泛型和构造函数的TypeScript强制转换类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基类,并在那里有子类.

I have a base class, and sub-classes there of.

这些类的实例被放入基类类型的集合中.

Instances of those classes get put in an collection with the type of the base class.

class Type extends Object {
    public static ID = 'type';
    public id = 'type';
    constructor() { super(); }
}

class TypeA extends Type {
    public static ID = 'type-a';
    public id = 'type-a';
    constructor() { super(); }
    public onlyA() { return 'only A has this method'; }
}

class TypeB extends Type {
    public static ID = 'type-b';
    public id = 'type-b';
    constructor() { super(); }
    public onlyB() { return 'only B has this method'; }
}

// Discards subclass type information:
const list: Type[] = [
    new TypeA(),
    new TypeB()
];

// Has inferred type: Type
const list0 = list[0];

现在,如果我知道正确的类型,则可以使用 as 来推广该类型:

Now if I know the correct type, I can use as to promote the type:

const list0asA = list0 as TypeA;
list0asA.onlyA();

但是我想做的是创建一个通用函数,该函数将动态检查实例,并在不匹配的情况下返回提升后的类型或 null .

What I'd like to do however is create a generic function that will dynamically check the instance, and return either the promoted type or null if it does not match.

我想出了以下几点,但这并不完全正确:

I came up with the following, but it's not quite right:

function castOrNull<
    C extends typeof Type
>(value: Type, Constructor: C): C | null {
    if (value.id !== Constructor.ID) {
        return null;
    }
    return value as C;
}

const list0castA = castOrNull(list0, TypeA);
if (list0castA) {
    list0asA.onlyA();
}

问题是我不是试图将变量强制转换为构造函数类型,而是该构造函数实例的类型,因此as和return类型不正确.

The problem is I'm not trying to cast the variable to the constructors type, but the type of an instance of that constructor, so the as and return types are not correct.

这确实可行,但是它需要显式设置泛型类型,即在使用时两次指定类型,这不理想.

Alternately, this does work, but it requires explicitly setting the generic type, meaning specifying the type twice when used, which is less-than-ideal.

function castOrNull<
    T extends Type
>(value: Type, Constructor: typeof Type): T | null {
    if (value.id !== Constructor.ID) {
        return null;
    }
    return value as T;
}

const list0upA = castOrNull<TypeA>(list0, TypeA);
if (list0castA) {
    list0asA.onlyA();
}

是否可以在不指定两次类型的情况下创建此泛型函数?

Is it possible to create this generic function without specifying the type twice?

推荐答案

从Typescript 2.8开始,将类型 InstanceType< T> 添加到标准库中,该库从构造函数类型中提取.> T 其实例的类型.因此,对于您的摘要,您可以将其用于返回类型并进行强制转换:

Starting in Typescript 2.8, the type InstanceType<T> was added to the standard lib, which extracts from a constructor type T the type of its instance. So for your snippet, you can use that for your return type and cast:

function castOrNull<
    C extends typeof Type
>(value: Type, Constructor: C): InstanceType<C> | null {
    if (value.id !== Constructor.ID) {
        return null;
    }
    return value as InstanceType<C>;
}

// All good now
const list0castA = castOrNull(list0, TypeA);
if (list0castA) {
    list0asA.onlyA();
}

这篇关于使用泛型和构造函数的TypeScript强制转换类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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