当其中一个类型为任何类型时,为什么类型推断不能用于联合类型?

时间:2016-08-30 16:40:28

标签: typescript

当我使用其中一个类型为any的联合类型时,TypeScript编辑器似乎无法正确解析该类型。我有以下人为的例子:

interface ITest {
    name: string;
    age: number;
}

interface ITest2 {
    last: string;
    dob: number;
}

function isGood(input: any) : input is ITest{
    return 'name' in input && 'age' in input;
}

function doIt(){
    var data : ITest2 | ITest  = {
        last: 'Test', dob: 123
    }

    var data2 : any | ITest = {
        name: 'else', age: 45
    }

    if(isGood(data)){
        alert(`name:${data.name}, age:${data.age}`); // data shows ITest
    }

    if(isGood(data2)){
        alert(`name:${data2.name}, age:${data2.age}`); // data2 shows any
    }
}

doIt();

代码正确执行,但设计时间体验并非我所期望的(在VS Code - 1.4.0和TypeScript playground - 1.8中)。

正如预期的那样,以下行根据类型保护推断data类型为ITest

alert(`name:${data.name}, age:${data.age}`); // data shows ITest

但是,第二部分(使用data2)并未推断出正确的类型,而且总是any

alert(`name:${data2.name}, age:${data2.age}`); // data2 shows any

在上面一行中,我希望intellisense知道data2的类型为ITest,就像之前为data一样。

我尝试在联合声明中交换2种类型,但它没有改变结果。

我错过了什么吗?

用例

我面临的真实用例是我收到了一些HTTP调用的响应。在线路上,它必须是any类型,因为HTTP客户端对我们的数据类型一无所知。

但是,我想写一个用户定义的类型保护,它检查我们想要的json对象的属性,然后只提取我们需要的数据并返回它。

1 个答案:

答案 0 :(得分:1)

它扩展了任何类型以包括类型防护。 any已经超过ITest,因此它会选择any。如果您将其更改为更窄的类型,则会正确推断ITest

var data2 : {} | ITest = {
    name: 'else', age: 45
}

发生这种情况的原因是因为any是可以想象的最宽的类型,它是同时出现的所有其他类型,所以any | ITest并不真正有意义,这只是与any相同。

编辑:我还想指出,只需删除该类型就可以正常工作,即使隐式任何已关闭也是如此。不确定这是否有用。示例:

var data2 = {
    name: 'else', age: 45
}

第二次编辑:稍微重写一下答案,以便更清楚,正如评论所示,有一些混乱。