为什么TypeScript的类型保护在父作用域中的工作方式不同?

时间:2016-09-26 12:17:15

标签: typescript

我有这段代码:

function isNumberArray(l: any[]): l is number[] {
    let res = true;
    for (let e of l) {
        res = res && (typeof e === 'number');
    }
    return res;
}
let arr:(number|string)[] = [1, 2];
if (isNumberArray(arr)) {
    let res1: number = arr[1]; //OK
    let res2: number = [1].map(i => arr[i])[0]; // ERROR: Type 'string | number' is not assignable to type 'number'
}

由于某种原因,变量arr在if块内的两行中有不同的类型。为什么呢?

1 个答案:

答案 0 :(得分:2)

好问题。这里的根本原因是TypeScript不知道立即调用回调,因此做出保守的假设,即可能在其他赋值发生之后调用该函数。

考虑一下这样的代码:

let x: string | number = "hello world";
foo(() => console.log(x.substr(2)));
x = 42;

此代码崩溃或成功吗?没有办法知道。这取决于foo是立即执行其回调还是稍后(例如foowindow.setTimeout)。它甚至可以做到这两点!

请注意,如果您说过const而不是let,那么TypeScript可以知道该变量“不会在以后”更改类型:

const arr:(number|string)[] = [1, 2];
if (isNumberArray(arr)) {
    let res1: number = arr[1]; //OK
    let res2: number = [1].map(i => arr[i])[0]; // OK
}