简体   繁体   English

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

[英]How does TypeScript infer the type of `this`?

The inference strategy of this in TypeScript is confusing to me, for example: 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

If you put the code into TypeScript Playground , and check the type of this inside f() , you can see that it's inferred to be of type this: this , which means the subtype of A . 如果将代码放入TypeScript Playground中 ,并在f()检查this的类型,则可以看到它的推断类型为this: this ,表示A的子类型。

In this situation, I think it means this is bind to A , and can't refer to the global object. 在这种情况下,我认为这意味着this绑定到A ,并且不能引用全局对象。 Otherwise, this should be inferred to be of type this: Any . 否则, this应该被推断为类型的this: Any

But actually, as shown in the invocation of f1() , if the function f is invoked outside the context of A , it could still be the global object. 但是实际上,如f1()调用所示,如果函数fA的上下文之外调用,则它仍然可能是全局对象。

So in my opinion, the inferred type of this inside f() should be this: Any , not this: this . 因此,我认为,在f()推断出的this类型应该是this: Any ,不是this: this And only if the function f is defined with arrow function could it be inferred to be this: this . 并且仅当函数f用箭头函数定义时,才可以推断为this: this For example: 例如:

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

So, is this a bug or a design feature? 那么,这是错误还是设计功能? How does TypeScript infer the type of this actually? 如何打字稿推断的类型this实际上是?

So in my opinion, the inferred type of this inside f() should be this: any, not this: this. 因此,我认为,在f()中推断出的this类型应该是this:any,而不是this:this。

well, yes. 嗯,是。 In some ways you're right. 在某些方面您是对的。 It is not 100% sure that this inside a class function is really an instance of the class. 不能100%地确定类函数中的this确实是该类的实例。 But typescript is not meant to be 100% accurate ! 但是打字稿并不意味着100%准确 This is important to understand! 了解这一点很重要! The type guarantees don't hold in all situations. 类型保证并非在所有情况下都适用。 They literally can't. 他们实际上不能。

Javascript is very dynamic. JavaScript 非常动态。 There is no way to just analyze all this dynamics at compile time. 没有办法仅在编译时分析所有这些动态。

So Typescript purely relies on assumptions and user provided type information. 因此,Typescript完全依赖于假设和用户提供的类型信息。 It should help you, but wont stop you when you want to shoot into your own feet. 它应该可以帮助您,但是当您想用自己的脚射击时,它不会阻止您。

Just never do this: 只是永远不要这样做:

const x = foo.x;
x();

actually this has the effect that older class models then ES6 classes like the ember object model are very hard to use with typescript - the assumptions just dont hold up. 实际上,这样做的结果是,像ember对象模型之类的ES6类之类的旧类模型很难与typescript一起使用-假设不成立。 And even the best typings have limitations. 甚至最好的打字也有局限性。 There are things you can do in JS you can not define in TS. 有些事情您可以在JS中完成,而您无法在TS中定义。 Still TS can be very helpful for all other cases. 对于所有其他情况,TS仍然很有帮助。

Great question. 好问题。 Typescript has what we call an unsound type system. Typescript具有我们所说的不健全的类型系统。 (Closure Compiler and Flow also have unsound type systems.) An unsound type system means that Typescript will sometimes compute a type for an expression that is wrong; (Closure Compiler和Flow也具有不健全的类型系统。)不健全的类型系统意味着Typescript有时会为错误的表达式计算类型;这是错误的。 it is different from the type that the expression will take at runtime. 它与表达式在运行时采用的类型不同。 As mentioned in the other reply, this happens because JavaScript is very dynamic, and type-system designers take a few shortcuts in order to tame the complexity. 正如在其他答复中所提到的,发生这种情况是因为JavaScript非常动态,并且类型系统设计人员采取了一些捷径来控制复杂性。

In your particular example, even though this can indeed by any , in practice it is almost always A , so that's what Typescript chooses. 在您的具体的例子,尽管this的确可以通过any ,在实践中几乎总是A ,所以这是打字稿选择。 However, it could potentially warn at f1() , because the method is called as a function (ie, without a this ). 但是,它可能会在f1()处发出警告,因为该方法被称为函数(即,没有this )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM