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:
Nathan Shively-Sanders 2018-08-23 08:21:28 -07:00 committed by GitHub
parent 5e8b63cd1d
commit 03653934c3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 1 deletions

View file

@ -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();

View 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 = {};

View file

@ -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))

View 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; }
>{} : {}

View file

@ -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 = {}