【问题标题】:TypeScript cast type using generics and constructor?使用泛型和构造函数的 TypeScript 类型转换?
【发布时间】:2018-09-21 20:49:06
【问题描述】:

我有一个基类和子类。

这些类的实例被放入具有基类类型的集合中。

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 来提升类型:

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

不过,我想做的是创建一个通用函数,该函数将动态检查实例,如果不匹配则返回提升的类型或 null

我想出了以下内容,但不太正确:

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 和返回类型不正确。

或者,这确实有效,但它需要显式设置泛型类型,这意味着在使用时指定类型两次,这不太理想。

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();
}

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

【问题讨论】:

  • 可以选择 typescript 2.8 吗?如果是这样,您可以使用InstanceType&lt;C&gt; 作为您的返回类型和强制转换。
  • @CRice 是的!这看起来不错!愿意发布答案吗?

标签: typescript generics casting


【解决方案1】:

从 Typescript 2.8 开始,类型 InstanceType&lt;T&gt; 被添加到标准库中,它从构造函数类型 T 中提取其实例的类型。因此,对于您的 sn-p,您可以将其用于您的返回类型和强制转换:

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();
}

【讨论】:

    猜你喜欢
    • 2019-09-19
    • 2019-05-04
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    • 2022-01-22
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多