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中,并检查this
中f()
的类型,您会发现它推断为this: this
类型,即表示A
的子类型。
在这种情况下,我认为这意味着this
已绑定到A
,并且无法引用全局对象。否则,应该推断this
的类型为this: Any
。
但是实际上,如f1()
的调用所示,如果在f
的上下文之外调用函数A
,它仍然可能是全局对象。
因此,我认为this
中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
的类型?
答案 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
的情况)。