diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index db02365fd17..070a5c2650b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16140,6 +16140,16 @@ namespace ts { return true; } case SpecialPropertyAssignmentKind.ThisProperty: + if (!binaryExpression.symbol || + binaryExpression.symbol.valueDeclaration && !!getJSDocTypeTag(binaryExpression.symbol.valueDeclaration)) { + return true; + } + const thisAccess = binaryExpression.left as PropertyAccessExpression; + if (!isObjectLiteralMethod(getThisContainer(thisAccess.expression, /*includeArrowFunctions*/ false))) { + return false; + } + const thisType = checkThisExpression(thisAccess.expression); + return thisType && !!getPropertyOfType(thisType, thisAccess.name.escapedText); case SpecialPropertyAssignmentKind.ModuleExports: return !binaryExpression.symbol || binaryExpression.symbol.valueDeclaration && !!getJSDocTypeTag(binaryExpression.symbol.valueDeclaration); default: diff --git a/tests/baselines/reference/typeFromContextualThisType.symbols b/tests/baselines/reference/typeFromContextualThisType.symbols new file mode 100644 index 00000000000..c243123491d --- /dev/null +++ b/tests/baselines/reference/typeFromContextualThisType.symbols @@ -0,0 +1,40 @@ +=== tests/cases/conformance/salsa/bug25926.js === +/** @type {{ a(): void; b?(n: number): number; }} */ +const o1 = { +>o1 : Symbol(o1, Decl(bug25926.js, 1, 5)) + + a() { +>a : Symbol(a, Decl(bug25926.js, 1, 12)) + + this.b = n => n; +>this.b : Symbol(b, Decl(bug25926.js, 0, 23)) +>this : Symbol(__type, Decl(bug25926.js, 0, 11)) +>b : Symbol(b, Decl(bug25926.js, 2, 9)) +>n : Symbol(n, Decl(bug25926.js, 3, 16)) +>n : Symbol(n, Decl(bug25926.js, 3, 16)) + } +}; + +/** @type {{ d(): void; e?(n: number): number; f?(n: number): number; g?: number }} */ +const o2 = { +>o2 : Symbol(o2, Decl(bug25926.js, 8, 5)) + + d() { +>d : Symbol(d, Decl(bug25926.js, 8, 12)) + + this.e = this.f = m => this.g || m; +>this.e : Symbol(e, Decl(bug25926.js, 7, 23)) +>this : Symbol(__type, Decl(bug25926.js, 7, 11)) +>e : Symbol(e, Decl(bug25926.js, 9, 9)) +>this.f : Symbol(f, Decl(bug25926.js, 7, 46)) +>this : Symbol(__type, Decl(bug25926.js, 7, 11)) +>f : Symbol(f, Decl(bug25926.js, 10, 16)) +>m : Symbol(m, Decl(bug25926.js, 10, 25)) +>this.g : Symbol(g, Decl(bug25926.js, 7, 69)) +>this : Symbol(__type, Decl(bug25926.js, 7, 11)) +>g : Symbol(g, Decl(bug25926.js, 7, 69)) +>m : Symbol(m, Decl(bug25926.js, 10, 25)) + } +}; + + diff --git a/tests/baselines/reference/typeFromContextualThisType.types b/tests/baselines/reference/typeFromContextualThisType.types new file mode 100644 index 00000000000..fc6e3961800 --- /dev/null +++ b/tests/baselines/reference/typeFromContextualThisType.types @@ -0,0 +1,48 @@ +=== tests/cases/conformance/salsa/bug25926.js === +/** @type {{ a(): void; b?(n: number): number; }} */ +const o1 = { +>o1 : { a(): void; } +>{ a() { this.b = n => n; }} : { a(): void; } + + a() { +>a : () => void + + this.b = n => n; +>this.b = n => n : (n: number) => number +>this.b : ((n: number) => number) | undefined +>this : { a(): void; } +>b : ((n: number) => number) | undefined +>n => n : (n: number) => number +>n : number +>n : number + } +}; + +/** @type {{ d(): void; e?(n: number): number; f?(n: number): number; g?: number }} */ +const o2 = { +>o2 : { d(): void; g?: number | undefined; } +>{ d() { this.e = this.f = m => this.g || m; }} : { d(): void; } + + d() { +>d : () => void + + this.e = this.f = m => this.g || m; +>this.e = this.f = m => this.g || m : (m: number) => number +>this.e : ((n: number) => number) | undefined +>this : { d(): void; g?: number | undefined; } +>e : ((n: number) => number) | undefined +>this.f = m => this.g || m : (m: number) => number +>this.f : ((n: number) => number) | undefined +>this : { d(): void; g?: number | undefined; } +>f : ((n: number) => number) | undefined +>m => this.g || m : (m: number) => number +>m : number +>this.g || m : number +>this.g : number | undefined +>this : { d(): void; g?: number | undefined; } +>g : number | undefined +>m : number + } +}; + + diff --git a/tests/cases/conformance/salsa/typeFromContextualThisType.ts b/tests/cases/conformance/salsa/typeFromContextualThisType.ts new file mode 100644 index 00000000000..062b238eb8d --- /dev/null +++ b/tests/cases/conformance/salsa/typeFromContextualThisType.ts @@ -0,0 +1,20 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @strict: true +// @Filename: bug25926.js + +/** @type {{ a(): void; b?(n: number): number; }} */ +const o1 = { + a() { + this.b = n => n; + } +}; + +/** @type {{ d(): void; e?(n: number): number; f?(n: number): number; g?: number }} */ +const o2 = { + d() { + this.e = this.f = m => this.g || m; + } +}; +