TypeScript如何推断“ this”的类型?

时间:2018-09-09 03:24:26

标签: javascript typescript types this type-inference

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中,并检查thisf()的类型,您会发现它推断为this: this类型,即表示A的子类型。

在这种情况下,我认为这意味着this已绑定到A,并且无法引用全局对象。否则,应该推断this的类型为this: Any

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

因此,我认为thisf()的推断类型应为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的类型?

2 个答案:

答案 0 :(得分:2)

  

因此,我认为,在f()中推断出的this应该是this:any,而不是this。this。

是的,是的。在某些方面您是对的。不能100%确定类函数内的this确实是该类的实例。但是打字稿并不意味着100%准确!了解这一点很重要!类型保证并非在所有情况下都适用。他们实际上不能。

JavaScript是动态的。无法在编译时分析所有这些动态。

因此Typescript完全依赖于假设和用户提供的类型信息。它应该可以帮助您,但是当您想用自己的脚射击时,它不会阻止您。

绝对不要这样做:

const x = foo.x;
x();

实际上,这会产生如下影响:打字机脚本很难使用比ES6类(例如ember对象模型)更老的模型-这些假设不会成立。甚至最好的打字也有局限性。有些事情您可以在JS中完成,而您无法在TS中定义。对于其他所有情况,TS仍然很有帮助。

答案 1 :(得分:1)

很好的问题。 Typescript具有我们所说的不健全的类型系统。 (Closure Compiler和Flow也具有不健全的类型系统。)不健全的类型系统意味着Typescript有时会为错误的表达式计算类型;这是错误的。它与表达式在运行时采用的类型不同。正如在其他答复中提到的那样,发生这种情况是因为JavaScript非常动态,并且类型系统设计人员采取了一些捷径来控制复杂性。

在您的特定示例中,尽管this确实可以any进行操作,但实际上它几乎总是A,因此正是Typescript选择的。但是,它可能会在f1()处发出警告,因为该方法被称为函数(即,没有this的情况)。