在泛型中投射 - 打字稿

时间:2018-06-07 16:41:16

标签: typescript generics casting

我有一个基类:

class ClassA {
    public prop1: string;
}

我有一个通用界面:

interface IMyInterface<T extends ClassA> {
    objA: T;
}

一个通用类:

class MyClass<T extends ClassA> implements IMyInterface<T> {
    public objA: T;

    public myMethod () {
        this.objA.prop1 = "foo"; // This is ok

        if ("prop2" in this.objA) {
            this.objA.prop2 = "bar"; // This is not
        }
    }
}

如果且仅当prop2中存在此属性时,如何强制objA objA

我是否必须强制演员(this.objA as ClassA & {prop2: string}).prop2 = "bar"

2 个答案:

答案 0 :(得分:2)

这似乎是Typescript的当前限制。我发现this issue描述了这个确切的情况。

解决方法与您已经提到的相同。您必须将this.objA转换为允许设置prop2字段的其他类型。所以:

(this.objA as ClassA & {prop2: string}).prop2 = "bar"

// Or to trade some safety for brevity:
(this.objA as any).prop2 = "bar"

否则,您还可以使用自定义类型保护来断言该密钥的存在。使用上面链接的问题,你可以这样做:

function inOperator<K extends string, T>(k: K, o: T): o is T & Record<K, any> {
    return k in o;
}

然后,使用它而不是in运算符:

if (inOperator("prop2", this.objA)) {
    this.objA.prop2 = "bar"; // No error now
}

答案 1 :(得分:1)

您可以在Type Guards and Differentiating Types会话中使用类型保护,如here所述

您的代码将如下所示:

class ClassA {
    public prop1: string;
}

interface IMyInterface<T extends ClassA> {
    objA: T;
}

interface IProp2 {
    prop2: string;
}

function hasProp2(obj: ClassA | IProp2): obj is IProp2 {
    return (<IProp2>obj).prop2 !== undefined;
}

class MyClass<T extends ClassA> implements IMyInterface<T> {
    public objA: T;

    public myMethod () {
        this.objA.prop1 = "foo"; // This is ok

        if (hasProp2(this.objA)){
            this.objA.prop2 = "bar"; // Now this is ok
        }
    }
}