53a756ea63
* Type `this` in more constructor functions Previously, `this: this` in constructor functions only when there was an explicit `@constructor` tag on the function. Now, `this: this` for any function that's known to be a constructor function. This improves completions inside constructor functions; also note that previously the compiler *did* type `this: this` inside methods of constructor functions, so this fix makes us more consistent. This is reflected in the large number of baselines that improve. The fix is a simple switch to `isJSConstructor`, which is the standard way to detect constructor functions. I'm not sure why the original PR didn't use this method. I remember discussing this limitation in the original bug, #25979, and I guess I decided that it made sense. But I was heavily primed by the bug's framing of the problem in terms of `noImplicitThis`, which *should* require an explicit `@constructor` tag. With better typing comes better detection of `@readonly` assignment; I had to fix the readonly detection code to use `isJSConstructor` as well. * Remove `Add @class tag` fix for noImplicitThis. The new rules mean that it never applies. It's possible that it should apply to functions like ```js function f() { this.init() } ``` In which `init` is never defined, but I think this program is incomplete enough that not offering the fix is fine. * Fix precedence of `@this` Previously, both `@class` and `@this` in a jsdoc would cause the `@this` annotation to be ignored. This became a worse problem with this PR, because `this` is correctly typed even without the annotation. This commit makes sure that `@this` is checked first and used if present.
95 lines
1.5 KiB
Plaintext
95 lines
1.5 KiB
Plaintext
=== tests/cases/conformance/salsa/a.js ===
|
|
/** @param {number} x */
|
|
function C(x) {
|
|
>C : typeof C
|
|
>x : number
|
|
|
|
this.x = x
|
|
>this.x = x : number
|
|
>this.x : any
|
|
>this : this
|
|
>x : any
|
|
>x : number
|
|
}
|
|
C.prototype.m = function() {
|
|
>C.prototype.m = function() { this.y = 12} : () => void
|
|
>C.prototype.m : any
|
|
>C.prototype : any
|
|
>C : typeof C
|
|
>prototype : any
|
|
>m : any
|
|
>function() { this.y = 12} : () => void
|
|
|
|
this.y = 12
|
|
>this.y = 12 : 12
|
|
>this.y : number | undefined
|
|
>this : this
|
|
>y : number | undefined
|
|
>12 : 12
|
|
}
|
|
var c = new C(1)
|
|
>c : C
|
|
>new C(1) : C
|
|
>C : typeof C
|
|
>1 : 1
|
|
|
|
c.x = undefined // should error
|
|
>c.x = undefined : undefined
|
|
>c.x : number
|
|
>c : C
|
|
>x : number
|
|
>undefined : undefined
|
|
|
|
c.y = undefined // ok
|
|
>c.y = undefined : undefined
|
|
>c.y : number | undefined
|
|
>c : C
|
|
>y : number | undefined
|
|
>undefined : undefined
|
|
|
|
/** @param {number} x */
|
|
function A(x) {
|
|
>A : typeof A
|
|
>x : number
|
|
|
|
if (!(this instanceof A)) {
|
|
>!(this instanceof A) : boolean
|
|
>(this instanceof A) : boolean
|
|
>this instanceof A : boolean
|
|
>this : this
|
|
>A : typeof A
|
|
|
|
return new A(x)
|
|
>new A(x) : A
|
|
>A : typeof A
|
|
>x : number
|
|
}
|
|
this.x = x
|
|
>this.x = x : number
|
|
>this.x : any
|
|
>this : this
|
|
>x : any
|
|
>x : number
|
|
}
|
|
var k = A(1)
|
|
>k : A
|
|
>A(1) : A
|
|
>A : typeof A
|
|
>1 : 1
|
|
|
|
var j = new A(2)
|
|
>j : A
|
|
>new A(2) : A
|
|
>A : typeof A
|
|
>2 : 2
|
|
|
|
k.x === j.x
|
|
>k.x === j.x : boolean
|
|
>k.x : number | undefined
|
|
>k : A
|
|
>x : number | undefined
|
|
>j.x : number | undefined
|
|
>j : A
|
|
>x : number | undefined
|
|
|