Don't create expando object literals in TS (#26525)
Previously, getWidenedTypedFromJSPropertyAssignment was not called for Typescript code. Since property assignments on functions, it is. That meant that property assignments would incorrectly create a JS container for empty object literals in a property assignment, even in Typescript: ```ts const one = () => 1 one.p = {} one.p.q = {} // should not work in Typescript! ``` Now empty object literals never create expando objects in Typescript, because getJSExpandoObjectType requires the declaration to be in a JS file.
This commit is contained in:
parent
5e8b63cd1d
commit
03653934c3
|
@ -4795,7 +4795,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function getJSExpandoObjectType(decl: Node, symbol: Symbol, init: Expression | undefined): Type | undefined {
|
||||
if (!init || !isObjectLiteralExpression(init) || init.properties.length) {
|
||||
if (!isInJavaScriptFile(decl) || !init || !isObjectLiteralExpression(init) || init.properties.length) {
|
||||
return undefined;
|
||||
}
|
||||
const exports = createSymbolTable();
|
||||
|
|
15
tests/baselines/reference/typeFromPropertyAssignment30.js
Normal file
15
tests/baselines/reference/typeFromPropertyAssignment30.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
//// [typeFromPropertyAssignment30.ts]
|
||||
interface Combo {
|
||||
(): number;
|
||||
p?: { [s: string]: number };
|
||||
}
|
||||
const c: Combo = () => 1
|
||||
// should not be an expando object, but contextually typed by Combo.p
|
||||
c.p = {}
|
||||
|
||||
|
||||
|
||||
//// [typeFromPropertyAssignment30.js]
|
||||
var c = function () { return 1; };
|
||||
// should not be an expando object, but contextually typed by Combo.p
|
||||
c.p = {};
|
|
@ -0,0 +1,20 @@
|
|||
=== tests/cases/conformance/salsa/typeFromPropertyAssignment30.ts ===
|
||||
interface Combo {
|
||||
>Combo : Symbol(Combo, Decl(typeFromPropertyAssignment30.ts, 0, 0))
|
||||
|
||||
(): number;
|
||||
p?: { [s: string]: number };
|
||||
>p : Symbol(Combo.p, Decl(typeFromPropertyAssignment30.ts, 1, 15))
|
||||
>s : Symbol(s, Decl(typeFromPropertyAssignment30.ts, 2, 11))
|
||||
}
|
||||
const c: Combo = () => 1
|
||||
>c : Symbol(c, Decl(typeFromPropertyAssignment30.ts, 4, 5), Decl(typeFromPropertyAssignment30.ts, 4, 24))
|
||||
>Combo : Symbol(Combo, Decl(typeFromPropertyAssignment30.ts, 0, 0))
|
||||
|
||||
// should not be an expando object, but contextually typed by Combo.p
|
||||
c.p = {}
|
||||
>c.p : Symbol(Combo.p, Decl(typeFromPropertyAssignment30.ts, 1, 15))
|
||||
>c : Symbol(c, Decl(typeFromPropertyAssignment30.ts, 4, 5), Decl(typeFromPropertyAssignment30.ts, 4, 24))
|
||||
>p : Symbol(Combo.p, Decl(typeFromPropertyAssignment30.ts, 1, 15))
|
||||
|
||||
|
21
tests/baselines/reference/typeFromPropertyAssignment30.types
Normal file
21
tests/baselines/reference/typeFromPropertyAssignment30.types
Normal file
|
@ -0,0 +1,21 @@
|
|||
=== tests/cases/conformance/salsa/typeFromPropertyAssignment30.ts ===
|
||||
interface Combo {
|
||||
(): number;
|
||||
p?: { [s: string]: number };
|
||||
>p : { [s: string]: number; }
|
||||
>s : string
|
||||
}
|
||||
const c: Combo = () => 1
|
||||
>c : Combo
|
||||
>() => 1 : { (): number; p: {}; }
|
||||
>1 : 1
|
||||
|
||||
// should not be an expando object, but contextually typed by Combo.p
|
||||
c.p = {}
|
||||
>c.p = {} : {}
|
||||
>c.p : { [s: string]: number; }
|
||||
>c : Combo
|
||||
>p : { [s: string]: number; }
|
||||
>{} : {}
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
interface Combo {
|
||||
(): number;
|
||||
p?: { [s: string]: number };
|
||||
}
|
||||
const c: Combo = () => 1
|
||||
// should not be an expando object, but contextually typed by Combo.p
|
||||
c.p = {}
|
||||
|
Loading…
Reference in a new issue