首页 > 解决方案 > TypeScript 如何推断 `this` 的类型?

问题描述

TypeScript 中的推理策略this让我很困惑,例如:

class A {
    s: String
    constructor() {
        this.s = "this is fine"
    }
    f() {
        console.log(this.s)
    }
}

let a = new A

a.f() // -> this is fine

let f1 = (new A).f
f1() // -> undefined

如果你把代码放到 TypeScript Playground中,检查thisinside的类型f(),你可以看到它被推断为 type this: this,也就是 的子类型A

在这种情况下,我认为这意味着this绑定到A,并且不能引用全局对象。否则,this应推断为 type this: Any

但实际上,如 的调用所示f1(),如果函数f在 的上下文之外调用A,它仍然可能是全局对象。

所以在我看来,thisinside的推断类型f()应该是this: Any,而不是this: this。并且只有f用箭头函数定义的函数才能推断为this: this. 例如:

class A {
    s: String
    constructor() {
        this.s = "this is fine"
    }
    f = () => {
        console.log(this.s)
    }
}

let a = new A

a.f() // -> this is fine

let f1 = (new A).f
f1() // -> this is fine

那么,这是错误还是设计功能?TypeScript 如何推断this实际的类型?

标签: javascripttypescripttypesthistype-inference

解决方案


所以在我看来,f() 中 this 的推断类型应该是 this:any,而不是 this:this。

嗯,是。在某些方面你是对的。不能 100% 确定this类函数内部确实是该类的实例。但打字稿并不意味着 100% 准确!理解这一点很重要!类型保证并非在所有情况下都成立。他们真的做不到。

Javascript 是非常动态的。没有办法只在编译时分析所有这些动态。

所以 Typescript 完全依赖于假设和用户提供的类型信息。它应该对您有所帮助,但当您想自己开枪时,它不会阻止您。

永远不要这样做:

const x = foo.x;
x();

实际上,这具有这样的效果,即旧的类模型然后 ES6 类(如 ember 对象模型)很难与 typescript 一起使用——假设只是站不住脚。即使是最好的打字也有局限性。有些事情你可以在 JS 中做你不能在 TS 中定义。对于所有其他情况,TS 仍然非常有帮助。


推荐阅读