检查变量是否是打字稿联合中的特定接口类型

Check if variable is a specific interface type in a typescript union

是否可以创建类型保护或其他实现相同目的的东西,以检查变量是否是打字稿联合体中的特定接口类型?

interface Foo { a:string }
interface Bar { b:string }

(function() {
    function doStuff(thing: Foo | Bar) {
        if(typeof thing === 'Foo') {
            console.log('Foo');
        } 
        else if (typeof thing === 'Bar') {
            console.log('Bar');
        }
        else {
            console.log('unknown');
        }
    }

    var thing: Foo = {a:'a'};
    doStuff(thing);
})();

typeof 不会这样做。它总是 return "string"、"number"、"boolean"、"object"、"function" 或 "undefined".

您可以使用 if(thing.a !== undefined) {if(thing.hasOwnProperty('a')) { 等测试来测试对象属性。

请注意,您可以创建一个同时具有 字符串 a 和字符串 b 的对象,因此请注意这种可能性。

在 TypeScript 2 中,您可以像这样使用 Discriminated Unions

interface Foo {
    kind: "foo";
    a:string;
}
interface Bar {
    kind: "bar";
    b:string;
}
type FooBar = Foo | Bar;
let thing: FooBar;

然后使用 if (thing.kind === "foo").

测试对象

如果您只有示例中的 2 个字段,我可能会像 @ryan-cavanaugh 提到的那样使用组合接口,并将两个属性设为可选:

interface FooBar {
    a?: string;
    b?: string
}

请注意,在 原始 示例中,使用 if (thing.a !== undefined) 测试对象会产生错误 Property 'a' does not exist on type 'Foo | Bar'.

并且使用 if (thing.hasOwnProperty('a')) 测试它不会在 if 语句中将类型缩小为 Foo

@ryan-cavanaugh TypesScript 2.0 或 2.1 有更好的方法吗?

从 Typescript 1.6 开始,您可以使用用户定义的类型保护:

let isFoo = (object: Foo| Bar): object is Foo => {
    return "a" in object;
}

https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards and https://github.com/microsoft/TypeScript/issues/10485