TypeScript/tests/baselines/reference/constructorFunctions3.types
Nathan Shively-Sanders 53a756ea63
Type this in more constructor functions (#39447)
* 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.
2020-07-08 08:44:17 -07:00

130 lines
2.2 KiB
Plaintext

=== tests/cases/conformance/salsa/a.js ===
function Instance() {
>Instance : typeof Instance
this.i = 'simple'
>this.i = 'simple' : "simple"
>this.i : any
>this : this
>i : any
>'simple' : "simple"
}
var i = new Instance();
>i : Instance
>new Instance() : Instance
>Instance : typeof Instance
Instance;
>Instance : typeof Instance
i;
>i : Instance
function StaticToo() {
>StaticToo : typeof StaticToo
this.i = 'more complex'
>this.i = 'more complex' : "more complex"
>this.i : any
>this : this
>i : any
>'more complex' : "more complex"
}
StaticToo.property = 'yep'
>StaticToo.property = 'yep' : "yep"
>StaticToo.property : string
>StaticToo : typeof StaticToo
>property : string
>'yep' : "yep"
var s = new StaticToo();
>s : StaticToo
>new StaticToo() : StaticToo
>StaticToo : typeof StaticToo
s;
>s : StaticToo
StaticToo;
>StaticToo : typeof StaticToo
// Both!
function A () {
>A : typeof A
this.x = 1
>this.x = 1 : 1
>this.x : any
>this : this
>x : any
>1 : 1
/** @type {1} */
this.second = 1
>this.second = 1 : 1
>this.second : 1
>this : this
>second : 1
>1 : 1
}
/** @param {number} n */
A.prototype.z = function f(n) {
>A.prototype.z = function f(n) { return n + this.x} : (n: number) => number
>A.prototype.z : any
>A.prototype : any
>A : typeof A
>prototype : any
>z : any
>function f(n) { return n + this.x} : (n: number) => number
>f : (n: number) => number
>n : number
return n + this.x
>n + this.x : number
>n : number
>this.x : number
>this : this
>x : number
}
/** @param {number} m */
A.t = function g(m) {
>A.t = function g(m) { return m + 1} : (m: number) => number
>A.t : (m: number) => number
>A : typeof A
>t : (m: number) => number
>function g(m) { return m + 1} : (m: number) => number
>g : (m: number) => number
>m : number
return m + 1
>m + 1 : number
>m : number
>1 : 1
}
var a = new A()
>a : A
>new A() : A
>A : typeof A
a.z(3)
>a.z(3) : number
>a.z : (n: number) => number
>a : A
>z : (n: number) => number
>3 : 3
A.t(2)
>A.t(2) : number
>A.t : (m: number) => number
>A : typeof A
>t : (m: number) => number
>2 : 2
a.second = 1
>a.second = 1 : 1
>a.second : 1
>a : A
>second : 1
>1 : 1