如果 obj 是类型之一,如何检查属性是否存在

Zyd*_*nar 6 typescript

假设我有几个接口 A、B、C 实现了公共 Base。

interface Base {
    x: number;
    y: number;
    z: number;
}

interface A extends Base {
    a: true;
}

interface B extends Base {
    b: true;
}

interface C extends Base {
    C: true;
}
Run Code Online (Sandbox Code Playgroud)

并使用 if 语句运行:

function foo(arg: A|B|C){
    if(arg.a!==undefined){//throws type error
        //do stuff for type a
    } else if(arg.b !== undefined){//throws type error
        //do stuff for type b
    } else if(arg.c !== undefined){ //throws type error
        //do stuff for type c
    }
}
Run Code Online (Sandbox Code Playgroud)

如何正确检查属性是否存在?我不想使用任何类型。是//@ts-ignore唯一的选择吗?

Tit*_*mir 10

Typescript 将只允许访问公共属性。由于您测试的属性并非对联合的所有成员通用,因此 typescript 不会让您访问它们。

您可以改用in类型保护来测试该属性是否存在。

interface Base {
    x: number;
    y: number;
    z: number;
}

interface A extends Base {
    a: true;
}

interface B extends Base {
    b: true;
}

interface C extends Base {
    C: true;
}

function foo(arg: A|B|C){
    if('a' in arg){
        arg.a
    } else if('b' in arg){
        arg.b
    } else { 
        arg.C
    }
}
Run Code Online (Sandbox Code Playgroud)


jo_*_*_va 5

您可以使用类型保护

function isA(arg: A | B | C): arg is A {
    return (<A>arg).a !== undefined;
}

function isB(arg: A | B | C): arg is B {
    return (<B>arg).b !== undefined;
}

function foo(arg: A | B | C) {
    if (isA(arg)) {
        // do stuff for type a
    } else if (isB(arg)) {
        // do stuff for type b
    } else {
        // do stuff for type c
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 在我看来,自定义类型防护在这种情况下是矫枉过正的 (3认同)