为什么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块内的两行中有不同的类型.为什么?

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

考虑一下这样的代码:

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

这段代码崩溃了,还是成功了?没有办法知道.这取决于foo是立即还是稍后执行其回调(例如foo是window.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
}
点赞