* Properly infer `this` in tagged `@constructor`s.
`c.prototype.method = function() { this }` was already supported.
This commit add support to two more kinds relying on the JSDoc
`@constructor` tag. These are:
1. `/** @constructor */ function Example() { this }`
2. `/** @constructor */ var Example = function() { this }`
* Update the baseline for js constructorFunctions.
C3 and C4 `this` was set as `any`, now it is properly showing as
the class type.
* Fix lint errors
* Add circular initialisers to constructo fn tests.
* Error (`TS2348`) if calling tagged js constructors
When calling a JS function explicitly tagged with either `@class` or
`@constructor` the checker should throw a TS2348 not callable error.
* Don't resolve jsdoc classes with construct sigs.
This undoes the last commit that sought to change how js functions
tagged with `@class` were inferred. For some reason, currently
unknown, giving those functions construct signatures causes issues
in property assignment/member resolution (as seen in the
`typeFromPropertyAssignment12` test case).
Instead of changing the signature resolution, the error is explicitly
generated in `resolveCallExpression` for those functions.
* Only bind module.exports if no local definition exists
Note that this uses `lookupSymbolForNameWorker`, which is really a
best-effort check since it only knows about symbols that it has already
encountered.
As a side-effect, even when `module` is bound as part of a
`module.exports` reference, it only declares it once instead of one
declaration per reference.
* Only type module.exports inside module files
It is an error inside script files, but the binder sometimes creates a
ModuleExports symbol because we doesn't know whether we have a commonjs
module until after binding is done.
* Only bind module.exports in a commonjs module
Note that this, too, is a best-effort check since evidence of
commonjs-ness may be found after a *reference* to module.exports. (A
reference to module.exports alone is not enough evidence that a file is
commonjs. It has to have an assignment to it.)
* Revert "Revert "Explicitly typed special assignments are context sensitive (#25619)""
This reverts commit 16676f2707.
* Revert "Revert "Explicitly typed prototype assignments are context sensitive (#25688)""
This reverts commit ff8c30d636.
* Initial, wasteful, solution
It burns a check flags. Probably necessary, but perhaps not.
I haven't accepted baselines, but they are a bit questionable. I'm not
sure the synthetic type is right, because I expected to see
{ "exports": typeof import("x") } but instead see { "x": typeof
import("x") }.
* Update some baselines
* module.exports= always uses lhs type
Conflicts between exports property assignments and exports assignments
should get a union type instead of an error.
* Fix lint and accept good user baselines
* Add tests based on user tests.
These currently fail.
* Fix all but 1 of user test bugs found by typing module.exports
Still quite messy and full of notes
* Follow merged symbols+allow any object type
This allows exports like `module.exports = new EE` to have properties
added to them.
Still messy, but I'm going to run user tests and look for regressions.
* Update improved user baselines
* Fix infinite recursion when checking module.exports
* Fix bogus use-before-def error
getExportSymbolOfValueSymbolIfExported should always merge its returned
symbol, whether it's symbol.exportSymbol or just symbol.
* Update user test baselines
* Cleanup
* More small cleanup
* Bind `module` of `module.exports` as a special symbol
Previously it was also special, but created during name resolution in
the checker. It made sense when there was only one special symbol for
all files, but now there is one `module` symbol per file.
* Explicitly typed prototype assignments:ctx sensitive
Follow up to #25619: Add the necessary code to type `prototype`
correctly in prototype assignments so that code like
`F.prototype = { ... }` properly makes the object literal context
sensitive.
* Fix lint
* Explicitly typed js assignments: context sensitive
Explicitly typed special assignments should be context sensitive if they
have an explicit type tag. Previously no special assignments were
context sensitive because they are declarations, and in the common,
untyped, case we inspect the right side of the assignment to get the
type of the left side, and inspect the right side of the assignment to
get the type of the left side, etc etc.
Note that some special assignments still return `any` from
checkExpression, so still don't get the right type.
Fixes#25571
* Change prototype property handling+update bselines
* Fix indentation in test
* Update baselines
Previously variable declaration+function expression worked.
Note that class expression/class declaration do not work, due to the way
they are specified. I added a test for future reference.
* Fix duplicate errors in js special assignments
* Simplify checkExpressionCached call to checkExpression
* Accept baselines after merge
* Use Map for deferredNodes and improve NoDeferredCheck comment
I added an assert when a duplicate was added, but it caused 18 failures
in our test suite.
* Remove NoDeferredCheck
* avoid circularity in getTypeOfVariableOrParameterOrProperty
Modify getTypeOfVariableOrParameterOrProperty to get the type of the
variable declaration before widening it. This essentially avoids some
circularities by (1) setting the type of the variable declaration to the
unwidened type (2) updating the type of the variable declaration to the
widened one.
You will still get a circular noImplicitAny in (1), for expressions that
actually are circular, but not in (2), for the containers of things that
are not themselves circular.
* Stop checking js init object literals via checkObjectLiteral
* checkBinaryExpression: new code for special assignments
* Chained lookup for js initializer type
* Check for JS-specific types only once
Also make sure to respect the type annotation if there is one.
* Accept API changes
Nearly everything in a merge of JS special assignments looks like a
valueDeclaration. This commit ensures that intermediate "module
declarations" are not used when a better valueDeclaration is available:
```js
// File1.js
var X = {}
X.Y.Z = class { }
// File2.js
X.Y = {}
```
In the above example, the `Y` in `X.Y.Z = class { }` was used as the
valueDeclaration for `Y` because it appeared before `X.Y = {}` in the
compilation.
This change exposed a bug in binding, #24703, that required a change in
typeFromPropertyAssignmentOutOfOrder. The test still fails for the
original reason it was created, and the new bug #24703 contains a repro.
Do this by not widening properties of an object literal that are
1. JS initialisers
2. and not an object literal
These properties have types that will never widen, so the compiler
shouldn't ask for the types earlier than it strictly needs to.
* Static assignments to class expressions work
* Bind static properties of functions too
Also update SymbolLinks in getTypeOfFuncClassEnumModule so that the
type gets cached correctly.
* Remove initializer handling:obj literals+type lookup
Also include a couple of improved baselines
* Fix 1-nested js containers:binding+cross-file merge
* Consolidate check into one utility
The utility is horrible and needs to change, but at least it's in one
place.
Next step is to make the utility like getDeclarationOfAlias, except
getDeclarationOfJSAlias.
* Defaulted assignments now (mostly) work
* Default assignment definitely work, and IIFEs kind of do
* n-nested undeclared containers now seem to work
Merging even seems to work ok.
* Handle prototype+prototype property assignments
Perhaps in the wrong way. I have an idea how to simplify them.
* Remove prototype special-case
1. It's not completely removed; the checker code in
getJavascriptClassType needs to be fixed, among other places.
2. I didn't actually remove the code so that it will be easier to see
what used to be there on Monday.
Regardless, the code will be much simpler and seems to be mostly
improved with very little work so far.
* Allow more merges+accept baselines
* Update more baselines
* Fix js initializer check in bindPropertyAssignment
* Fix codefixes
* Rest of strictNullChecks cleanup + other cleanup
1. Remove a few TODOs
2. Remove extraneous SymbolFlag
3. Simplify isSameDefaultedName
* Binder cleanup
* Checker cleanup
* Almost done with utilities cleanup
* Utilities cleanup
* Require js initializer to be (1) JS (2) initializer
Change getDeclarationOfJSInitializer to require that the provided js
initializer be in a javascript file, and that it is the initializer of
the retrieved declaration.
* Use getSymbolOfNode instead of accessing symbol directly
* Ugh. Start over with just test cases
* Handle additional cases in getTypeOfVariableOrParameterOrProperty
These are cases in a really embarrassing check, in which we admit that
the symbol flags steered us wrong and switch to
getTypeOfFuncClassEnumModule instead (which never asserts).
* Add test case for #24111
* Address PR comments
* Fix resolution of exported types in commonjs
It is fine to resolve the types of exported classes in ES6:
```js
export class C {
}
var c = new C()
```
But not for commonjs exported classes:
```js
module.exports.C = class {
}
var c = new C() // should error
```
Fixes#24492
* All jsdoc type aliases are available locally in commonjs modules
* Check that location isSourceFile before commonJsModuleIndicator
A bug in checkSpecialAssignment added bogus duplicate identifier errors
when using module.exports assignment to export a class. This commit
fixes that.
* JS initializers use original valueDecl, not mutated
target's valueDeclaration is set to the source's if it is not present.
This makes it incorrect to use getJSInitializerSymbol because it relies
on the symbol's valueDeclaration.
This fix just saves the original valueDeclaration before mutating and
uses that.
* Compare merged targetInitializer to target
Instead of the unmerged one
* Add test of stack overflow
If the base type has a property by that name, add it to the list
constructor types to make it as authoritative as special assignments
found in the constructor.
1. Allow assignment to `exports`.
2. The type of the rhs is not checked against the type of `exports`
since they are aliased declarations.
To support more complex patterns like `exports = c.name = c`, we may
have to treat `c.name` as a declaration. That will be more complicated
than this PR.
* Combining symbol and removing error done but messy
* Small fix + add new test baselines
All other tests are unchanged
* Union conflicting assignment types+better names
* Add tests and update baselines
* Check commonjs export= from resolveExternalModuleSymbol
* Fix crash in type resolution in JS IIFEs
We recognise IIFEs as JS special assignment initialisers, but not as
containers otherwise. That means that IIFEs will not have a symbol
unless they have an *outside* assignment.
The permanent fix will be to make IIFEs a container, based on the
containership of the value that they return. This fix does not do that;
it just makes type resolution return undefined instead of crashing.
* Comment the IIFE-fix line
* Print js-constructor function type names
Instead of printing them as a type literal, which is scary.
* Use assigned name for functions and classes
That otherwise have no name. This helps quick info for javascript a
*lot*. Typescript mainly benefits when printing the type of class
expressions.
* Improve names of functions in binding elements
Also fix some fourslash baselines
* First draft:in js, constructor declaration is preferred
* Add tests
* initializer of null|undefined gives any in JS
Also move this-assignment fixes out of binder. I'm going to put it in
the checker instead.
* In JS, initializer null|undefined: any, []: any[]
* First draft of js prefer-ctor-types overhaul
* Update tests, update baselines
* Improve readability of constructor-type preference
* Cleanup: Remove TODO and duplication
* Add noImplicitAny errors
* Add comment
* Track thisContainer for this-property-assignments in JS
Previously it would update on every block, not just those that could
bind `this`.
In addition, if the constructor symbol still can't be found, then no
binding happens. This is usually OK because people don't add new
properties in methods too often.
* Update additional baselines
* Add lib:dom to new test
* Address PR comments
* Correct new name for saveThisParentContainer
* Add test case and temporarily disable inference
(Inference of class members from this-assignments inside a
prototype-assigned function.)
* Update baselines
* In blocks and source files, bind functions first
* Add tests from other bugs
* Remove temporary failsafe
* Update tests to restore intent and clean up errors
* Restore intent even better
* Restore intent even better x2
* Add missed baselines
* Do not add undefined for this assignments in functions
* Test:constructor functions with --strict
* First draft -- works, but needs a stricter check added
* Update baselines
* Make undefined-skip stricter and more efficient
Symbol-based now instead of syntactic
* Exclude prototype function assignments
* Add explanatory comment
Previously, this would assert:
```ts
exports.undeclared.n = 1;
```
Because undeclared was never declared in any recognised way. Now it no
longer asserts, but does not bind. That's because the full pattern
starts with the line `exports = require('./x')` and assumes that x.js
declares `undeclared`. I am not sure how to bind this. The new test
contains this pattern in case I figure it out.