打字稿类型守卫和粗箭头功能

Typescript Type Guards and fat arrow function

这不应该正确编译吗?我在突出显示的行中收到错误 "Property 'hello' does not exist on type 'object'."。

我可以在胖箭头函数之外访问 g.hello 没有问题。

class Test {
    constructor() {
    }
    hello() : string {
        return "Hello";
    }
}

let g : object;

if (g instanceof Test) {
    () => {
        g.hello();    ////// ERROR HERE /////
    };
}

类型保护对变量(或其他任何东西)所做的缩小不会跨越函数边界。这是设计限制。

解决此问题的一种方法是将 g 分配给一个新变量,该变量将根据缩小范围推断其类型。在箭头函数中访问新变量将按预期工作:

class Test {
    constructor() {
    }
    hello() : string {
        return "Hello";
    }
}

let g : object;

if (g instanceof Test) {
    const gTest = g;
    () => {
        gTest.hello();
    };
}

如果 g 不变,解决此问题的另一种方法是用 const 声明 g。这将使编译器保留缩小范围:

let g : object;

if (g instanceof Test) {
    const gTest = g;
    () => {
        gTest.hello();
    };
}

Playground Link

let + 箭头函数

class Test {
    constructor() {
    }
    hello() : string {
        return "Hello";
    }
}

declare let g : object;

if (g instanceof Test) {
    () => {
        g.hello(); // error
    };
}

g在定义函数的时候是一个Test,但是在函数运行的时候g可能不是Test

const + 箭头函数

class Test {
    constructor() {
    }
    hello() : string {
        return "Hello";
    }
}

declare const g : object;

if (g instanceof Test) {
    () => {
        g.hello(); // ok
    };
}

g是不可变的,g在函数定义后总是一个Test

const + 正则函数

class Test {
    constructor() {
    }
    hello() : string {
        return "Hello";
    }
}

declare const g : object;

if (g instanceof Test) {
    function f() {
        g.hello(); // error
    };
}

在底层实现中,常规函数 f 由 ES5 var 定义,而不是 ES6 letvariable hoisting 提升声明 f,当 g 可能不是 Test.