【问题标题】:Check if variable is a specific interface type in a typescript union检查变量是否是打字稿联合中的特定接口类型
【发布时间】:2015-05-24 05:08:06
【问题描述】:

是否可以创建一个 typeguard 或其他实现相同目的的东西来检查变量是否是 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);
})();

【问题讨论】:

    标签: typescript typescript1.4


    【解决方案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-guardshttps://github.com/microsoft/TypeScript/issues/10485

    【讨论】:

    • 这是最好的答案!
    • 这里的一个重要答案是 'key' in object 被 TypeScript 理解为一种区分接口的方式。可悲的是 typeof object.key === 'undefined' 在这种情况下失败了。
    • 这种方法的一个问题是,如果a被重命名为aa,代码仍然可以编译,即使a不再是Foo接口的判别器。实际上,最好不要使用类型保护,而只需使用in 进行内联成员检查。然后编译器将推断类型 - 只要aFoo 的一部分。有人对此有更安全的方法吗?
    • @JørgenTvedt 这确实是主要问题。我对此问题的解决方案非常感兴趣。
    【解决方案2】:

    typeof 不这样做。它总是返回“字符串”、“数字”、“布尔”、“对象”、“函数”或“未定义”。

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

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

    【讨论】:

    • 那么如果不检查特定属性(如我们示例中的“a”),就无法检查变量是否符合接口?
    【解决方案3】:

    在 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
    }
    

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

    并且使用if (thing.hasOwnProperty('a')) 对其进行测试不会将if 语句中的类型缩小到Foo

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

    【讨论】:

    • 这是对联合、IMO 进行编译器检查的最安全方法,也是处理 OP 问题的最佳方法。我认为这是现在最好的答案@myartsev
    猜你喜欢
    • 2019-05-26
    • 1970-01-01
    • 2018-12-07
    • 2021-10-26
    • 1970-01-01
    • 2020-07-17
    • 2020-09-02
    • 2017-09-16
    • 1970-01-01
    相关资源
    最近更新 更多