* 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.
185 lines
3.1 KiB
Plaintext
185 lines
3.1 KiB
Plaintext
=== tests/cases/conformance/salsa/index.js ===
|
|
function C1() {
|
|
>C1 : typeof C1
|
|
|
|
if (!(this instanceof C1)) return new C1();
|
|
>!(this instanceof C1) : boolean
|
|
>(this instanceof C1) : boolean
|
|
>this instanceof C1 : boolean
|
|
>this : this
|
|
>C1 : typeof C1
|
|
>new C1() : C1
|
|
>C1 : typeof C1
|
|
|
|
this.x = 1;
|
|
>this.x = 1 : 1
|
|
>this.x : any
|
|
>this : this
|
|
>x : any
|
|
>1 : 1
|
|
}
|
|
|
|
const c1_v1 = C1();
|
|
>c1_v1 : C1
|
|
>C1() : C1
|
|
>C1 : typeof C1
|
|
|
|
const c1_v2 = new C1();
|
|
>c1_v2 : C1
|
|
>new C1() : C1
|
|
>C1 : typeof C1
|
|
|
|
var C2 = function () {
|
|
>C2 : typeof C2
|
|
>function () { if (!(this instanceof C2)) return new C2(); this.x = 1;} : typeof C2
|
|
|
|
if (!(this instanceof C2)) return new C2();
|
|
>!(this instanceof C2) : boolean
|
|
>(this instanceof C2) : boolean
|
|
>this instanceof C2 : boolean
|
|
>this : this
|
|
>C2 : typeof C2
|
|
>new C2() : C2
|
|
>C2 : typeof C2
|
|
|
|
this.x = 1;
|
|
>this.x = 1 : 1
|
|
>this.x : any
|
|
>this : this
|
|
>x : any
|
|
>1 : 1
|
|
|
|
};
|
|
|
|
const c2_v1 = C2();
|
|
>c2_v1 : C2
|
|
>C2() : C2
|
|
>C2 : typeof C2
|
|
|
|
const c2_v2 = new C2();
|
|
>c2_v2 : C2
|
|
>new C2() : C2
|
|
>C2 : typeof C2
|
|
|
|
/** @class */
|
|
function C3() {
|
|
>C3 : typeof C3
|
|
|
|
if (!(this instanceof C3)) return new C3();
|
|
>!(this instanceof C3) : boolean
|
|
>(this instanceof C3) : boolean
|
|
>this instanceof C3 : boolean
|
|
>this : this
|
|
>C3 : typeof C3
|
|
>new C3() : C3
|
|
>C3 : typeof C3
|
|
|
|
};
|
|
|
|
const c3_v1 = C3(); // error: @class tag requires 'new'
|
|
>c3_v1 : any
|
|
>C3() : any
|
|
>C3 : typeof C3
|
|
|
|
const c3_v2 = new C3();
|
|
>c3_v2 : C3
|
|
>new C3() : C3
|
|
>C3 : typeof C3
|
|
|
|
/** @class */
|
|
var C4 = function () {
|
|
>C4 : typeof C4
|
|
>function () { if (!(this instanceof C4)) return new C4();} : typeof C4
|
|
|
|
if (!(this instanceof C4)) return new C4();
|
|
>!(this instanceof C4) : boolean
|
|
>(this instanceof C4) : boolean
|
|
>this instanceof C4 : boolean
|
|
>this : this
|
|
>C4 : typeof C4
|
|
>new C4() : C4
|
|
>C4 : typeof C4
|
|
|
|
};
|
|
|
|
const c4_v1 = C4(); // error: @class tag requires 'new'
|
|
>c4_v1 : any
|
|
>C4() : any
|
|
>C4 : typeof C4
|
|
|
|
const c4_v2 = new C4();
|
|
>c4_v2 : C4
|
|
>new C4() : C4
|
|
>C4 : typeof C4
|
|
|
|
var c5_v1;
|
|
>c5_v1 : any
|
|
|
|
c5_v1 = function f() { };
|
|
>c5_v1 = function f() { } : () => void
|
|
>c5_v1 : any
|
|
>function f() { } : () => void
|
|
>f : () => void
|
|
|
|
new c5_v1();
|
|
>new c5_v1() : any
|
|
>c5_v1 : () => void
|
|
|
|
var c5_v2;
|
|
>c5_v2 : any
|
|
|
|
c5_v2 = class { };
|
|
>c5_v2 = class { } : typeof c5_v2
|
|
>c5_v2 : any
|
|
>class { } : typeof c5_v2
|
|
|
|
new c5_v2();
|
|
>new c5_v2() : c5_v2
|
|
>c5_v2 : typeof c5_v2
|
|
|
|
/** @class */
|
|
function C6() {
|
|
>C6 : typeof C6
|
|
|
|
this.functions = [x => x, x => x + 1, x => x - 1]
|
|
>this.functions = [x => x, x => x + 1, x => x - 1] : ((x: any) => any)[]
|
|
>this.functions : any
|
|
>this : this
|
|
>functions : any
|
|
>[x => x, x => x + 1, x => x - 1] : ((x: any) => any)[]
|
|
>x => x : (x: any) => any
|
|
>x : any
|
|
>x : any
|
|
>x => x + 1 : (x: any) => any
|
|
>x : any
|
|
>x + 1 : any
|
|
>x : any
|
|
>1 : 1
|
|
>x => x - 1 : (x: any) => number
|
|
>x : any
|
|
>x - 1 : number
|
|
>x : any
|
|
>1 : 1
|
|
|
|
};
|
|
|
|
var c6_v1 = new C6();
|
|
>c6_v1 : C6
|
|
>new C6() : C6
|
|
>C6 : typeof C6
|
|
|
|
|
|
/**
|
|
* @constructor
|
|
* @param {number} num
|
|
*/
|
|
function C7(num) {}
|
|
>C7 : typeof C7
|
|
>num : number
|
|
|
|
var c7_v1 = new C7();
|
|
>c7_v1 : C7
|
|
>new C7() : C7
|
|
>C7 : typeof C7
|
|
|