Explicitly typed special assignments are context sensitive (#25619)
* 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
This commit is contained in:
parent
f500289a44
commit
32e60a9647
|
@ -15785,22 +15785,22 @@ namespace ts {
|
|||
}
|
||||
|
||||
// In an assignment expression, the right operand is contextually typed by the type of the left operand.
|
||||
// Don't do this for special property assignments to avoid circularity.
|
||||
// Don't do this for special property assignments unless there is a type tag on the assignment, to avoid circularity from checking the right operand.
|
||||
function isContextSensitiveAssignment(binaryExpression: BinaryExpression): boolean {
|
||||
const kind = getSpecialPropertyAssignmentKind(binaryExpression);
|
||||
switch (kind) {
|
||||
case SpecialPropertyAssignmentKind.None:
|
||||
return true;
|
||||
case SpecialPropertyAssignmentKind.Property:
|
||||
case SpecialPropertyAssignmentKind.ExportsProperty:
|
||||
case SpecialPropertyAssignmentKind.Prototype:
|
||||
case SpecialPropertyAssignmentKind.PrototypeProperty:
|
||||
// If `binaryExpression.left` was assigned a symbol, then this is a new declaration; otherwise it is an assignment to an existing declaration.
|
||||
// See `bindStaticPropertyAssignment` in `binder.ts`.
|
||||
return !binaryExpression.left.symbol;
|
||||
case SpecialPropertyAssignmentKind.ExportsProperty:
|
||||
case SpecialPropertyAssignmentKind.ModuleExports:
|
||||
case SpecialPropertyAssignmentKind.PrototypeProperty:
|
||||
return !binaryExpression.left.symbol || binaryExpression.left.symbol.valueDeclaration && !!getJSDocTypeTag(binaryExpression.left.symbol.valueDeclaration);
|
||||
case SpecialPropertyAssignmentKind.ThisProperty:
|
||||
case SpecialPropertyAssignmentKind.Prototype:
|
||||
return false;
|
||||
case SpecialPropertyAssignmentKind.ModuleExports:
|
||||
return !binaryExpression.symbol || binaryExpression.symbol.valueDeclaration && !!getJSDocTypeTag(binaryExpression.symbol.valueDeclaration);
|
||||
default:
|
||||
return Debug.assertNever(kind);
|
||||
}
|
||||
|
|
|
@ -7,11 +7,11 @@ export function abc(a, b, c) { return 5; }
|
|||
>5 : 5
|
||||
|
||||
module.exports = { abc };
|
||||
>module.exports = { abc } : { [x: string]: any; abc: (a: any, b: any, c: any) => number; }
|
||||
>module.exports = { abc } : { abc: (a: any, b: any, c: any) => number; }
|
||||
>module.exports : any
|
||||
>module : any
|
||||
>exports : any
|
||||
>{ abc } : { [x: string]: any; abc: (a: any, b: any, c: any) => number; }
|
||||
>{ abc } : { abc: (a: any, b: any, c: any) => number; }
|
||||
>abc : (a: any, b: any, c: any) => number
|
||||
|
||||
=== tests/cases/conformance/salsa/use.js ===
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
tests/cases/conformance/salsa/mod.js(5,7): error TS7006: Parameter 'n' implicitly has an 'any' type.
|
||||
tests/cases/conformance/salsa/test.js(52,7): error TS7006: Parameter 'n' implicitly has an 'any' type.
|
||||
tests/cases/conformance/salsa/test.js(70,7): error TS7006: Parameter 'n' implicitly has an 'any' type.
|
||||
|
||||
|
||||
==== tests/cases/conformance/salsa/test.js (2 errors) ====
|
||||
/** @typedef {{
|
||||
status: 'done'
|
||||
m(n: number): void
|
||||
}} DoneStatus */
|
||||
|
||||
// property assignment
|
||||
var ns = {}
|
||||
/** @type {DoneStatus} */
|
||||
ns.x = {
|
||||
status: 'done',
|
||||
m(n) { }
|
||||
}
|
||||
|
||||
ns.x = {
|
||||
status: 'done',
|
||||
m(n) { }
|
||||
}
|
||||
ns.x
|
||||
|
||||
|
||||
// this-property assignment
|
||||
class Thing {
|
||||
constructor() {
|
||||
/** @type {DoneStatus} */
|
||||
this.s = {
|
||||
status: 'done',
|
||||
m(n) { }
|
||||
}
|
||||
}
|
||||
|
||||
fail() {
|
||||
this.s = {
|
||||
status: 'done',
|
||||
m(n) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// exports-property assignment
|
||||
|
||||
/** @type {DoneStatus} */
|
||||
exports.x = {
|
||||
status: "done",
|
||||
m(n) { }
|
||||
}
|
||||
exports.x
|
||||
|
||||
/** @type {DoneStatus} contextual typing is allowed, but module.exports.y: any.
|
||||
Guess it doesn't check the type tag? */
|
||||
module.exports.y = {
|
||||
status: "done",
|
||||
m(n) { }
|
||||
~
|
||||
!!! error TS7006: Parameter 'n' implicitly has an 'any' type.
|
||||
}
|
||||
module.exports.y
|
||||
|
||||
// prototype-property assignment
|
||||
/** @type {DoneStatus} */
|
||||
Thing.prototype.x = {
|
||||
status: 'done',
|
||||
m(n) { }
|
||||
}
|
||||
Thing.prototype.x
|
||||
|
||||
// prototype assignment
|
||||
function F() {
|
||||
}
|
||||
/** @type {DoneStatus} */
|
||||
F.prototype = {
|
||||
status: "done",
|
||||
m(n) { }
|
||||
~
|
||||
!!! error TS7006: Parameter 'n' implicitly has an 'any' type.
|
||||
}
|
||||
|
||||
==== tests/cases/conformance/salsa/mod.js (1 errors) ====
|
||||
// module.exports assignment
|
||||
/** @type {{ status: 'done' }} */
|
||||
module.exports = {
|
||||
status: "done",
|
||||
m(n) { }
|
||||
~
|
||||
!!! error TS7006: Parameter 'n' implicitly has an 'any' type.
|
||||
}
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
=== tests/cases/conformance/salsa/test.js ===
|
||||
/** @typedef {{
|
||||
status: 'done'
|
||||
m(n: number): void
|
||||
}} DoneStatus */
|
||||
|
||||
// property assignment
|
||||
var ns = {}
|
||||
>ns : Symbol(ns, Decl(test.js, 6, 3))
|
||||
|
||||
/** @type {DoneStatus} */
|
||||
ns.x = {
|
||||
>ns.x : Symbol(ns.x, Decl(test.js, 6, 11), Decl(test.js, 11, 1))
|
||||
>ns : Symbol(ns, Decl(test.js, 6, 3))
|
||||
>x : Symbol(ns.x, Decl(test.js, 6, 11), Decl(test.js, 11, 1))
|
||||
|
||||
status: 'done',
|
||||
>status : Symbol(status, Decl(test.js, 8, 8))
|
||||
|
||||
m(n) { }
|
||||
>m : Symbol(m, Decl(test.js, 9, 19))
|
||||
>n : Symbol(n, Decl(test.js, 10, 6))
|
||||
}
|
||||
|
||||
ns.x = {
|
||||
>ns.x : Symbol(ns.x, Decl(test.js, 6, 11), Decl(test.js, 11, 1))
|
||||
>ns : Symbol(ns, Decl(test.js, 6, 3))
|
||||
>x : Symbol(ns.x, Decl(test.js, 6, 11), Decl(test.js, 11, 1))
|
||||
|
||||
status: 'done',
|
||||
>status : Symbol(status, Decl(test.js, 13, 8))
|
||||
|
||||
m(n) { }
|
||||
>m : Symbol(m, Decl(test.js, 14, 19))
|
||||
>n : Symbol(n, Decl(test.js, 15, 6))
|
||||
}
|
||||
ns.x
|
||||
>ns.x : Symbol(ns.x, Decl(test.js, 6, 11), Decl(test.js, 11, 1))
|
||||
>ns : Symbol(ns, Decl(test.js, 6, 3))
|
||||
>x : Symbol(ns.x, Decl(test.js, 6, 11), Decl(test.js, 11, 1))
|
||||
|
||||
|
||||
// this-property assignment
|
||||
class Thing {
|
||||
>Thing : Symbol(Thing, Decl(test.js, 17, 4))
|
||||
|
||||
constructor() {
|
||||
/** @type {DoneStatus} */
|
||||
this.s = {
|
||||
>this.s : Symbol(Thing.s, Decl(test.js, 22, 19), Decl(test.js, 30, 12))
|
||||
>this : Symbol(Thing, Decl(test.js, 17, 4))
|
||||
>s : Symbol(Thing.s, Decl(test.js, 22, 19), Decl(test.js, 30, 12))
|
||||
|
||||
status: 'done',
|
||||
>status : Symbol(status, Decl(test.js, 24, 18))
|
||||
|
||||
m(n) { }
|
||||
>m : Symbol(m, Decl(test.js, 25, 27))
|
||||
>n : Symbol(n, Decl(test.js, 26, 14))
|
||||
}
|
||||
}
|
||||
|
||||
fail() {
|
||||
>fail : Symbol(Thing.fail, Decl(test.js, 28, 5))
|
||||
|
||||
this.s = {
|
||||
>this.s : Symbol(Thing.s, Decl(test.js, 22, 19), Decl(test.js, 30, 12))
|
||||
>this : Symbol(Thing, Decl(test.js, 17, 4))
|
||||
>s : Symbol(Thing.s, Decl(test.js, 22, 19), Decl(test.js, 30, 12))
|
||||
|
||||
status: 'done',
|
||||
>status : Symbol(status, Decl(test.js, 31, 18))
|
||||
|
||||
m(n) { }
|
||||
>m : Symbol(m, Decl(test.js, 32, 27))
|
||||
>n : Symbol(n, Decl(test.js, 33, 14))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// exports-property assignment
|
||||
|
||||
/** @type {DoneStatus} */
|
||||
exports.x = {
|
||||
>exports.x : Symbol(x, Decl(test.js, 36, 1))
|
||||
>exports : Symbol(x, Decl(test.js, 36, 1))
|
||||
>x : Symbol(x, Decl(test.js, 36, 1))
|
||||
|
||||
status: "done",
|
||||
>status : Symbol(status, Decl(test.js, 41, 13))
|
||||
|
||||
m(n) { }
|
||||
>m : Symbol(m, Decl(test.js, 42, 19))
|
||||
>n : Symbol(n, Decl(test.js, 43, 6))
|
||||
}
|
||||
exports.x
|
||||
>exports.x : Symbol(x, Decl(test.js, 36, 1))
|
||||
>exports : Symbol("tests/cases/conformance/salsa/test", Decl(test.js, 0, 0))
|
||||
>x : Symbol(x, Decl(test.js, 36, 1))
|
||||
|
||||
/** @type {DoneStatus} contextual typing is allowed, but module.exports.y: any.
|
||||
Guess it doesn't check the type tag? */
|
||||
module.exports.y = {
|
||||
>module.exports : Symbol(y, Decl(test.js, 45, 9))
|
||||
>module : Symbol(module)
|
||||
>y : Symbol(y, Decl(test.js, 45, 9))
|
||||
|
||||
status: "done",
|
||||
>status : Symbol(status, Decl(test.js, 49, 20))
|
||||
|
||||
m(n) { }
|
||||
>m : Symbol(m, Decl(test.js, 50, 19))
|
||||
>n : Symbol(n, Decl(test.js, 51, 6))
|
||||
}
|
||||
module.exports.y
|
||||
>module : Symbol(module)
|
||||
|
||||
// prototype-property assignment
|
||||
/** @type {DoneStatus} */
|
||||
Thing.prototype.x = {
|
||||
>Thing.prototype.x : Symbol(Thing.x, Decl(test.js, 53, 16))
|
||||
>Thing.prototype : Symbol(Thing.x, Decl(test.js, 53, 16))
|
||||
>Thing : Symbol(Thing, Decl(test.js, 17, 4))
|
||||
>prototype : Symbol(Thing.prototype)
|
||||
>x : Symbol(Thing.x, Decl(test.js, 53, 16))
|
||||
|
||||
status: 'done',
|
||||
>status : Symbol(status, Decl(test.js, 57, 21))
|
||||
|
||||
m(n) { }
|
||||
>m : Symbol(m, Decl(test.js, 58, 19))
|
||||
>n : Symbol(n, Decl(test.js, 59, 6))
|
||||
}
|
||||
Thing.prototype.x
|
||||
>Thing.prototype.x : Symbol(Thing.x, Decl(test.js, 53, 16))
|
||||
>Thing.prototype : Symbol(Thing.prototype)
|
||||
>Thing : Symbol(Thing, Decl(test.js, 17, 4))
|
||||
>prototype : Symbol(Thing.prototype)
|
||||
>x : Symbol(Thing.x, Decl(test.js, 53, 16))
|
||||
|
||||
// prototype assignment
|
||||
function F() {
|
||||
>F : Symbol(F, Decl(test.js, 61, 17), Decl(test.js, 65, 1))
|
||||
}
|
||||
/** @type {DoneStatus} */
|
||||
F.prototype = {
|
||||
>F.prototype : Symbol(F.prototype, Decl(test.js, 65, 1))
|
||||
>F : Symbol(F, Decl(test.js, 61, 17), Decl(test.js, 65, 1))
|
||||
>prototype : Symbol(F.prototype, Decl(test.js, 65, 1))
|
||||
|
||||
status: "done",
|
||||
>status : Symbol(status, Decl(test.js, 67, 15))
|
||||
|
||||
m(n) { }
|
||||
>m : Symbol(m, Decl(test.js, 68, 19))
|
||||
>n : Symbol(n, Decl(test.js, 69, 6))
|
||||
}
|
||||
|
||||
=== tests/cases/conformance/salsa/mod.js ===
|
||||
// module.exports assignment
|
||||
/** @type {{ status: 'done' }} */
|
||||
module.exports = {
|
||||
>module : Symbol(export=, Decl(mod.js, 0, 0))
|
||||
>exports : Symbol(export=, Decl(mod.js, 0, 0))
|
||||
|
||||
status: "done",
|
||||
>status : Symbol(status, Decl(mod.js, 2, 18))
|
||||
|
||||
m(n) { }
|
||||
>m : Symbol(m, Decl(mod.js, 3, 19))
|
||||
>n : Symbol(n, Decl(mod.js, 4, 6))
|
||||
}
|
||||
|
208
tests/baselines/reference/contextualTypedSpecialAssignment.types
Normal file
208
tests/baselines/reference/contextualTypedSpecialAssignment.types
Normal file
|
@ -0,0 +1,208 @@
|
|||
=== tests/cases/conformance/salsa/test.js ===
|
||||
/** @typedef {{
|
||||
status: 'done'
|
||||
m(n: number): void
|
||||
}} DoneStatus */
|
||||
|
||||
// property assignment
|
||||
var ns = {}
|
||||
>ns : { [x: string]: any; x: { status: "done"; m(n: number): void; }; }
|
||||
>{} : { [x: string]: any; }
|
||||
|
||||
/** @type {DoneStatus} */
|
||||
ns.x = {
|
||||
>ns.x = { status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
|
||||
>ns.x : { status: "done"; m(n: number): void; }
|
||||
>ns : { [x: string]: any; x: { status: "done"; m(n: number): void; }; }
|
||||
>x : { status: "done"; m(n: number): void; }
|
||||
>{ status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
|
||||
|
||||
status: 'done',
|
||||
>status : "done"
|
||||
>'done' : "done"
|
||||
|
||||
m(n) { }
|
||||
>m : (n: number) => void
|
||||
>n : number
|
||||
}
|
||||
|
||||
ns.x = {
|
||||
>ns.x = { status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
|
||||
>ns.x : { status: "done"; m(n: number): void; }
|
||||
>ns : { [x: string]: any; x: { status: "done"; m(n: number): void; }; }
|
||||
>x : { status: "done"; m(n: number): void; }
|
||||
>{ status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
|
||||
|
||||
status: 'done',
|
||||
>status : "done"
|
||||
>'done' : "done"
|
||||
|
||||
m(n) { }
|
||||
>m : (n: number) => void
|
||||
>n : number
|
||||
}
|
||||
ns.x
|
||||
>ns.x : { status: "done"; m(n: number): void; }
|
||||
>ns : { [x: string]: any; x: { status: "done"; m(n: number): void; }; }
|
||||
>x : { status: "done"; m(n: number): void; }
|
||||
|
||||
|
||||
// this-property assignment
|
||||
class Thing {
|
||||
>Thing : Thing
|
||||
|
||||
constructor() {
|
||||
/** @type {DoneStatus} */
|
||||
this.s = {
|
||||
>this.s = { status: 'done', m(n) { } } : { status: "done"; m(n: number): void; }
|
||||
>this.s : { status: "done"; m(n: number): void; }
|
||||
>this : this
|
||||
>s : { status: "done"; m(n: number): void; }
|
||||
>{ status: 'done', m(n) { } } : { status: "done"; m(n: number): void; }
|
||||
|
||||
status: 'done',
|
||||
>status : "done"
|
||||
>'done' : "done"
|
||||
|
||||
m(n) { }
|
||||
>m : (n: number) => void
|
||||
>n : number
|
||||
}
|
||||
}
|
||||
|
||||
fail() {
|
||||
>fail : () => void
|
||||
|
||||
this.s = {
|
||||
>this.s = { status: 'done', m(n) { } } : { status: "done"; m(n: number): void; }
|
||||
>this.s : { status: "done"; m(n: number): void; }
|
||||
>this : this
|
||||
>s : { status: "done"; m(n: number): void; }
|
||||
>{ status: 'done', m(n) { } } : { status: "done"; m(n: number): void; }
|
||||
|
||||
status: 'done',
|
||||
>status : "done"
|
||||
>'done' : "done"
|
||||
|
||||
m(n) { }
|
||||
>m : (n: number) => void
|
||||
>n : number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// exports-property assignment
|
||||
|
||||
/** @type {DoneStatus} */
|
||||
exports.x = {
|
||||
>exports.x = { status: "done", m(n) { }} : { status: "done"; m(n: number): void; }
|
||||
>exports.x : { status: "done"; m(n: number): void; }
|
||||
>exports : typeof import("tests/cases/conformance/salsa/test")
|
||||
>x : { status: "done"; m(n: number): void; }
|
||||
>{ status: "done", m(n) { }} : { status: "done"; m(n: number): void; }
|
||||
|
||||
status: "done",
|
||||
>status : "done"
|
||||
>"done" : "done"
|
||||
|
||||
m(n) { }
|
||||
>m : (n: number) => void
|
||||
>n : number
|
||||
}
|
||||
exports.x
|
||||
>exports.x : { status: "done"; m(n: number): void; }
|
||||
>exports : typeof import("tests/cases/conformance/salsa/test")
|
||||
>x : { status: "done"; m(n: number): void; }
|
||||
|
||||
/** @type {DoneStatus} contextual typing is allowed, but module.exports.y: any.
|
||||
Guess it doesn't check the type tag? */
|
||||
module.exports.y = {
|
||||
>module.exports.y = { status: "done", m(n) { }} : { status: string; m(n: any): void; }
|
||||
>module.exports.y : any
|
||||
>module.exports : any
|
||||
>module : any
|
||||
>exports : any
|
||||
>y : any
|
||||
>{ status: "done", m(n) { }} : { status: string; m(n: any): void; }
|
||||
|
||||
status: "done",
|
||||
>status : string
|
||||
>"done" : "done"
|
||||
|
||||
m(n) { }
|
||||
>m : (n: any) => void
|
||||
>n : any
|
||||
}
|
||||
module.exports.y
|
||||
>module.exports.y : any
|
||||
>module.exports : any
|
||||
>module : any
|
||||
>exports : any
|
||||
>y : any
|
||||
|
||||
// prototype-property assignment
|
||||
/** @type {DoneStatus} */
|
||||
Thing.prototype.x = {
|
||||
>Thing.prototype.x = { status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
|
||||
>Thing.prototype.x : { status: "done"; m(n: number): void; }
|
||||
>Thing.prototype : Thing
|
||||
>Thing : typeof Thing
|
||||
>prototype : Thing
|
||||
>x : { status: "done"; m(n: number): void; }
|
||||
>{ status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
|
||||
|
||||
status: 'done',
|
||||
>status : "done"
|
||||
>'done' : "done"
|
||||
|
||||
m(n) { }
|
||||
>m : (n: number) => void
|
||||
>n : number
|
||||
}
|
||||
Thing.prototype.x
|
||||
>Thing.prototype.x : { status: "done"; m(n: number): void; }
|
||||
>Thing.prototype : Thing
|
||||
>Thing : typeof Thing
|
||||
>prototype : Thing
|
||||
>x : { status: "done"; m(n: number): void; }
|
||||
|
||||
// prototype assignment
|
||||
function F() {
|
||||
>F : typeof F
|
||||
}
|
||||
/** @type {DoneStatus} */
|
||||
F.prototype = {
|
||||
>F.prototype = { status: "done", m(n) { }} : { status: string; m(n: any): void; }
|
||||
>F.prototype : { [x: string]: any; }
|
||||
>F : typeof F
|
||||
>prototype : { [x: string]: any; }
|
||||
>{ status: "done", m(n) { }} : { status: string; m(n: any): void; }
|
||||
|
||||
status: "done",
|
||||
>status : string
|
||||
>"done" : "done"
|
||||
|
||||
m(n) { }
|
||||
>m : (n: any) => void
|
||||
>n : any
|
||||
}
|
||||
|
||||
=== tests/cases/conformance/salsa/mod.js ===
|
||||
// module.exports assignment
|
||||
/** @type {{ status: 'done' }} */
|
||||
module.exports = {
|
||||
>module.exports = { status: "done", m(n) { }} : { status: string; m(n: any): void; }
|
||||
>module.exports : any
|
||||
>module : any
|
||||
>exports : any
|
||||
>{ status: "done", m(n) { }} : { status: string; m(n: any): void; }
|
||||
|
||||
status: "done",
|
||||
>status : string
|
||||
>"done" : "done"
|
||||
|
||||
m(n) { }
|
||||
>m : (n: any) => void
|
||||
>n : any
|
||||
}
|
||||
|
|
@ -223,19 +223,19 @@ multipleDeclarationAlias5.func9 = function () { };
|
|||
>function () { } : () => void
|
||||
|
||||
var multipleDeclarationAlias6 = exports = module.exports = {};
|
||||
>multipleDeclarationAlias6 : { [x: string]: any; }
|
||||
>exports = module.exports = {} : { [x: string]: any; }
|
||||
>multipleDeclarationAlias6 : {}
|
||||
>exports = module.exports = {} : {}
|
||||
>exports : typeof import("tests/cases/conformance/salsa/b")
|
||||
>module.exports = {} : { [x: string]: any; }
|
||||
>module.exports = {} : {}
|
||||
>module.exports : any
|
||||
>module : any
|
||||
>exports : any
|
||||
>{} : { [x: string]: any; }
|
||||
>{} : {}
|
||||
|
||||
multipleDeclarationAlias6.func10 = function () { };
|
||||
>multipleDeclarationAlias6.func10 = function () { } : () => void
|
||||
>multipleDeclarationAlias6.func10 : any
|
||||
>multipleDeclarationAlias6 : { [x: string]: any; }
|
||||
>multipleDeclarationAlias6 : {}
|
||||
>func10 : any
|
||||
>function () { } : () => void
|
||||
|
||||
|
@ -294,13 +294,13 @@ module.exports.func12 = function () { };
|
|||
>function () { } : () => void
|
||||
|
||||
exports = module.exports = {};
|
||||
>exports = module.exports = {} : { [x: string]: any; }
|
||||
>exports = module.exports = {} : {}
|
||||
>exports : typeof import("tests/cases/conformance/salsa/b")
|
||||
>module.exports = {} : { [x: string]: any; }
|
||||
>module.exports = {} : {}
|
||||
>module.exports : any
|
||||
>module : any
|
||||
>exports : any
|
||||
>{} : { [x: string]: any; }
|
||||
>{} : {}
|
||||
|
||||
exports.func13 = function () { };
|
||||
>exports.func13 = function () { } : () => void
|
||||
|
@ -319,13 +319,13 @@ module.exports.func14 = function () { };
|
|||
>function () { } : () => void
|
||||
|
||||
exports = module.exports = {};
|
||||
>exports = module.exports = {} : { [x: string]: any; }
|
||||
>exports = module.exports = {} : {}
|
||||
>exports : typeof import("tests/cases/conformance/salsa/b")
|
||||
>module.exports = {} : { [x: string]: any; }
|
||||
>module.exports = {} : {}
|
||||
>module.exports : any
|
||||
>module : any
|
||||
>exports : any
|
||||
>{} : { [x: string]: any; }
|
||||
>{} : {}
|
||||
|
||||
exports.func15 = function () { };
|
||||
>exports.func15 = function () { } : () => void
|
||||
|
@ -369,11 +369,11 @@ module.exports.func18 = function () { };
|
|||
>function () { } : () => void
|
||||
|
||||
module.exports = {};
|
||||
>module.exports = {} : { [x: string]: any; }
|
||||
>module.exports = {} : {}
|
||||
>module.exports : any
|
||||
>module : any
|
||||
>exports : any
|
||||
>{} : { [x: string]: any; }
|
||||
>{} : {}
|
||||
|
||||
exports.func19 = function () { };
|
||||
>exports.func19 = function () { } : () => void
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
// @checkJs: true
|
||||
// @allowJs: true
|
||||
// @noEmit: true
|
||||
// @Filename: test.js
|
||||
// @strict: true
|
||||
/** @typedef {{
|
||||
status: 'done'
|
||||
m(n: number): void
|
||||
}} DoneStatus */
|
||||
|
||||
// property assignment
|
||||
var ns = {}
|
||||
/** @type {DoneStatus} */
|
||||
ns.x = {
|
||||
status: 'done',
|
||||
m(n) { }
|
||||
}
|
||||
|
||||
ns.x = {
|
||||
status: 'done',
|
||||
m(n) { }
|
||||
}
|
||||
ns.x
|
||||
|
||||
|
||||
// this-property assignment
|
||||
class Thing {
|
||||
constructor() {
|
||||
/** @type {DoneStatus} */
|
||||
this.s = {
|
||||
status: 'done',
|
||||
m(n) { }
|
||||
}
|
||||
}
|
||||
|
||||
fail() {
|
||||
this.s = {
|
||||
status: 'done',
|
||||
m(n) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// exports-property assignment
|
||||
|
||||
/** @type {DoneStatus} */
|
||||
exports.x = {
|
||||
status: "done",
|
||||
m(n) { }
|
||||
}
|
||||
exports.x
|
||||
|
||||
/** @type {DoneStatus} contextual typing is allowed, but module.exports.y: any.
|
||||
Guess it doesn't check the type tag? */
|
||||
module.exports.y = {
|
||||
status: "done",
|
||||
m(n) { }
|
||||
}
|
||||
module.exports.y
|
||||
|
||||
// prototype-property assignment
|
||||
/** @type {DoneStatus} */
|
||||
Thing.prototype.x = {
|
||||
status: 'done',
|
||||
m(n) { }
|
||||
}
|
||||
Thing.prototype.x
|
||||
|
||||
// prototype assignment
|
||||
function F() {
|
||||
}
|
||||
/** @type {DoneStatus} */
|
||||
F.prototype = {
|
||||
status: "done",
|
||||
m(n) { }
|
||||
}
|
||||
|
||||
// @Filename: mod.js
|
||||
// module.exports assignment
|
||||
/** @type {{ status: 'done' }} */
|
||||
module.exports = {
|
||||
status: "done",
|
||||
m(n) { }
|
||||
}
|
Loading…
Reference in a new issue