TypeScript/tests/baselines/reference/constructorFunctionsStrict.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

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