Skip to content

Commit

Permalink
don't drop index signatures when spreading object
Browse files Browse the repository at this point in the history
  • Loading branch information
ajafff committed Dec 27, 2018
1 parent b8def16 commit a626e4e
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 50 deletions.
20 changes: 19 additions & 1 deletion src/compiler/checker.ts
Expand Up @@ -6949,7 +6949,7 @@ namespace ts {
}

function unionSpreadIndexInfos(info1: IndexInfo | undefined, info2: IndexInfo | undefined): IndexInfo | undefined {
return info1 && info2 && createIndexInfo(
return !info1 ? info2 : !info2 ? info1 : createIndexInfo(
getUnionType([info1.type, info2.type]), info1.isReadonly || info2.isReadonly);
}

Expand Down Expand Up @@ -10273,6 +10273,24 @@ namespace ts {
}
}

if (stringIndexInfo || numberIndexInfo) {
const addToNumberIndex: Type[] = [];
const addToStringIndex: Type[] = [];
members.forEach((symbol, key) => {
const type = getTypeOfSymbol(symbol);
addToStringIndex.push(type);
if (isNumericLiteralName(key)) {
addToNumberIndex.push(type);
}
});
if (stringIndexInfo) {
stringIndexInfo = createIndexInfo(getUnionType([stringIndexInfo.type, ...addToStringIndex]), stringIndexInfo.isReadonly);
}
if (numberIndexInfo) {
numberIndexInfo = createIndexInfo(getUnionType([numberIndexInfo.type, ...addToNumberIndex]), numberIndexInfo.isReadonly);
}
}

const spread = createAnonymousType(
symbol,
members,
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/objectRest.types
Expand Up @@ -206,7 +206,7 @@ var { [computed]: stillNotGreat, [computed2]: soSo, ...o } = o;
({ [computed]: stillNotGreat, [computed2]: soSo, ...o } = o);
>({ [computed]: stillNotGreat, [computed2]: soSo, ...o } = o) : { a: number; b: string; }
>{ [computed]: stillNotGreat, [computed2]: soSo, ...o } = o : { a: number; b: string; }
>{ [computed]: stillNotGreat, [computed2]: soSo, ...o } : { a: number; b: string; }
>{ [computed]: stillNotGreat, [computed2]: soSo, ...o } : { [x: string]: any; a: number; b: string; }
>[computed] : any
>computed : string
>stillNotGreat : any
Expand Down
12 changes: 6 additions & 6 deletions tests/baselines/reference/objectSpreadComputedProperty.types
Expand Up @@ -16,24 +16,24 @@ function f() {
>null : null

const o1 = { ...{}, [n]: n };
>o1 : {}
>{ ...{}, [n]: n } : {}
>o1 : { [x: number]: number; }
>{ ...{}, [n]: n } : { [x: number]: number; }
>{} : {}
>[n] : number
>n : number
>n : number

const o2 = { ...{}, [a]: n };
>o2 : {}
>{ ...{}, [a]: n } : {}
>o2 : { [x: number]: number; }
>{ ...{}, [a]: n } : { [x: number]: number; }
>{} : {}
>[a] : number
>a : any
>n : number

const o3 = { [a]: n, ...{}, [n]: n, ...{}, [m]: m };
>o3 : {}
>{ [a]: n, ...{}, [n]: n, ...{}, [m]: m } : {}
>o3 : { [x: number]: number; }
>{ [a]: n, ...{}, [n]: n, ...{}, [m]: m } : { [x: number]: number; }
>[a] : number
>a : any
>n : number
Expand Down
23 changes: 0 additions & 23 deletions tests/baselines/reference/objectSpreadIndexSignature.errors.txt

This file was deleted.

34 changes: 33 additions & 1 deletion tests/baselines/reference/objectSpreadIndexSignature.js
Expand Up @@ -2,6 +2,7 @@
declare let indexed1: { [n: string]: number; a: number; };
declare let indexed2: { [n: string]: boolean; c: boolean; };
declare let indexed3: { [n: string]: number };
declare let indexed4: { [n: number]: number };
let i = { ...indexed1, b: 11 };
// only indexed has indexer, so i[101]: any
i[101];
Expand All @@ -15,7 +16,24 @@ indexed3 = { ...b ? indexed3 : undefined };
declare var roindex: { readonly [x:string]: number };
var writable = { ...roindex };
writable.a = 0; // should be ok.


var mixed = { foo: true, ...indexed3, bar: 'bar' };
mixed.foo; // boolean
mixed.bar; // string
mixed.baz; // string | number | boolean

var mixed2 = { foo: true, ...indexed4, bar: 'bar' };
mixed2.foo; // boolean
mixed2.bar; // string
mixed2[1]; // number

var mixed3 = { ...indexed4, '1': 'foo'};
mixed3[0]; // string | number
mixed3[1]; // string

var mixed4 = { ...indexed3, '1': 'foo'};
mixed4.foo; // string | number
mixed4[1]; // string

//// [objectSpreadIndexSignature.js]
"use strict";
Expand All @@ -39,3 +57,17 @@ ii[1001];
indexed3 = __assign({}, b ? indexed3 : undefined);
var writable = __assign({}, roindex);
writable.a = 0; // should be ok.
var mixed = __assign({ foo: true }, indexed3, { bar: 'bar' });
mixed.foo; // boolean
mixed.bar; // string
mixed.baz; // string | number | boolean
var mixed2 = __assign({ foo: true }, indexed4, { bar: 'bar' });
mixed2.foo; // boolean
mixed2.bar; // string
mixed2[1]; // number
var mixed3 = __assign({}, indexed4, { '1': 'foo' });
mixed3[0]; // string | number
mixed3[1]; // string
var mixed4 = __assign({}, indexed3, { '1': 'foo' });
mixed4.foo; // string | number
mixed4[1]; // string
90 changes: 78 additions & 12 deletions tests/baselines/reference/objectSpreadIndexSignature.symbols
Expand Up @@ -13,41 +13,107 @@ declare let indexed3: { [n: string]: number };
>indexed3 : Symbol(indexed3, Decl(objectSpreadIndexSignature.ts, 2, 11))
>n : Symbol(n, Decl(objectSpreadIndexSignature.ts, 2, 25))

declare let indexed4: { [n: number]: number };
>indexed4 : Symbol(indexed4, Decl(objectSpreadIndexSignature.ts, 3, 11))
>n : Symbol(n, Decl(objectSpreadIndexSignature.ts, 3, 25))

let i = { ...indexed1, b: 11 };
>i : Symbol(i, Decl(objectSpreadIndexSignature.ts, 3, 3))
>i : Symbol(i, Decl(objectSpreadIndexSignature.ts, 4, 3))
>indexed1 : Symbol(indexed1, Decl(objectSpreadIndexSignature.ts, 0, 11))
>b : Symbol(b, Decl(objectSpreadIndexSignature.ts, 3, 22))
>b : Symbol(b, Decl(objectSpreadIndexSignature.ts, 4, 22))

// only indexed has indexer, so i[101]: any
i[101];
>i : Symbol(i, Decl(objectSpreadIndexSignature.ts, 3, 3))
>i : Symbol(i, Decl(objectSpreadIndexSignature.ts, 4, 3))

let ii = { ...indexed1, ...indexed2 };
>ii : Symbol(ii, Decl(objectSpreadIndexSignature.ts, 6, 3))
>ii : Symbol(ii, Decl(objectSpreadIndexSignature.ts, 7, 3))
>indexed1 : Symbol(indexed1, Decl(objectSpreadIndexSignature.ts, 0, 11))
>indexed2 : Symbol(indexed2, Decl(objectSpreadIndexSignature.ts, 1, 11))

// both have indexer, so i[1001]: number | boolean
ii[1001];
>ii : Symbol(ii, Decl(objectSpreadIndexSignature.ts, 6, 3))
>ii : Symbol(ii, Decl(objectSpreadIndexSignature.ts, 7, 3))

declare const b: boolean;
>b : Symbol(b, Decl(objectSpreadIndexSignature.ts, 10, 13))
>b : Symbol(b, Decl(objectSpreadIndexSignature.ts, 11, 13))

indexed3 = { ...b ? indexed3 : undefined };
>indexed3 : Symbol(indexed3, Decl(objectSpreadIndexSignature.ts, 2, 11))
>b : Symbol(b, Decl(objectSpreadIndexSignature.ts, 10, 13))
>b : Symbol(b, Decl(objectSpreadIndexSignature.ts, 11, 13))
>indexed3 : Symbol(indexed3, Decl(objectSpreadIndexSignature.ts, 2, 11))
>undefined : Symbol(undefined)

declare var roindex: { readonly [x:string]: number };
>roindex : Symbol(roindex, Decl(objectSpreadIndexSignature.ts, 13, 11))
>x : Symbol(x, Decl(objectSpreadIndexSignature.ts, 13, 33))
>roindex : Symbol(roindex, Decl(objectSpreadIndexSignature.ts, 14, 11))
>x : Symbol(x, Decl(objectSpreadIndexSignature.ts, 14, 33))

var writable = { ...roindex };
>writable : Symbol(writable, Decl(objectSpreadIndexSignature.ts, 14, 3))
>roindex : Symbol(roindex, Decl(objectSpreadIndexSignature.ts, 13, 11))
>writable : Symbol(writable, Decl(objectSpreadIndexSignature.ts, 15, 3))
>roindex : Symbol(roindex, Decl(objectSpreadIndexSignature.ts, 14, 11))

writable.a = 0; // should be ok.
>writable : Symbol(writable, Decl(objectSpreadIndexSignature.ts, 14, 3))
>writable : Symbol(writable, Decl(objectSpreadIndexSignature.ts, 15, 3))

var mixed = { foo: true, ...indexed3, bar: 'bar' };
>mixed : Symbol(mixed, Decl(objectSpreadIndexSignature.ts, 18, 3))
>foo : Symbol(foo, Decl(objectSpreadIndexSignature.ts, 18, 13))
>indexed3 : Symbol(indexed3, Decl(objectSpreadIndexSignature.ts, 2, 11))
>bar : Symbol(bar, Decl(objectSpreadIndexSignature.ts, 18, 37))

mixed.foo; // boolean
>mixed.foo : Symbol(foo, Decl(objectSpreadIndexSignature.ts, 18, 13))
>mixed : Symbol(mixed, Decl(objectSpreadIndexSignature.ts, 18, 3))
>foo : Symbol(foo, Decl(objectSpreadIndexSignature.ts, 18, 13))

mixed.bar; // string
>mixed.bar : Symbol(bar, Decl(objectSpreadIndexSignature.ts, 18, 37))
>mixed : Symbol(mixed, Decl(objectSpreadIndexSignature.ts, 18, 3))
>bar : Symbol(bar, Decl(objectSpreadIndexSignature.ts, 18, 37))

mixed.baz; // string | number | boolean
>mixed : Symbol(mixed, Decl(objectSpreadIndexSignature.ts, 18, 3))

var mixed2 = { foo: true, ...indexed4, bar: 'bar' };
>mixed2 : Symbol(mixed2, Decl(objectSpreadIndexSignature.ts, 23, 3))
>foo : Symbol(foo, Decl(objectSpreadIndexSignature.ts, 23, 14))
>indexed4 : Symbol(indexed4, Decl(objectSpreadIndexSignature.ts, 3, 11))
>bar : Symbol(bar, Decl(objectSpreadIndexSignature.ts, 23, 38))

mixed2.foo; // boolean
>mixed2.foo : Symbol(foo, Decl(objectSpreadIndexSignature.ts, 23, 14))
>mixed2 : Symbol(mixed2, Decl(objectSpreadIndexSignature.ts, 23, 3))
>foo : Symbol(foo, Decl(objectSpreadIndexSignature.ts, 23, 14))

mixed2.bar; // string
>mixed2.bar : Symbol(bar, Decl(objectSpreadIndexSignature.ts, 23, 38))
>mixed2 : Symbol(mixed2, Decl(objectSpreadIndexSignature.ts, 23, 3))
>bar : Symbol(bar, Decl(objectSpreadIndexSignature.ts, 23, 38))

mixed2[1]; // number
>mixed2 : Symbol(mixed2, Decl(objectSpreadIndexSignature.ts, 23, 3))

var mixed3 = { ...indexed4, '1': 'foo'};
>mixed3 : Symbol(mixed3, Decl(objectSpreadIndexSignature.ts, 28, 3))
>indexed4 : Symbol(indexed4, Decl(objectSpreadIndexSignature.ts, 3, 11))
>'1' : Symbol('1', Decl(objectSpreadIndexSignature.ts, 28, 27))

mixed3[0]; // string | number
>mixed3 : Symbol(mixed3, Decl(objectSpreadIndexSignature.ts, 28, 3))

mixed3[1]; // string
>mixed3 : Symbol(mixed3, Decl(objectSpreadIndexSignature.ts, 28, 3))
>1 : Symbol('1', Decl(objectSpreadIndexSignature.ts, 28, 27))

var mixed4 = { ...indexed3, '1': 'foo'};
>mixed4 : Symbol(mixed4, Decl(objectSpreadIndexSignature.ts, 32, 3))
>indexed3 : Symbol(indexed3, Decl(objectSpreadIndexSignature.ts, 2, 11))
>'1' : Symbol('1', Decl(objectSpreadIndexSignature.ts, 32, 27))

mixed4.foo; // string | number
>mixed4 : Symbol(mixed4, Decl(objectSpreadIndexSignature.ts, 32, 3))

mixed4[1]; // string
>mixed4 : Symbol(mixed4, Decl(objectSpreadIndexSignature.ts, 32, 3))
>1 : Symbol('1', Decl(objectSpreadIndexSignature.ts, 32, 27))

98 changes: 92 additions & 6 deletions tests/baselines/reference/objectSpreadIndexSignature.types
Expand Up @@ -13,17 +13,21 @@ declare let indexed3: { [n: string]: number };
>indexed3 : { [n: string]: number; }
>n : string

declare let indexed4: { [n: number]: number };
>indexed4 : { [n: number]: number; }
>n : number

let i = { ...indexed1, b: 11 };
>i : { b: number; a: number; }
>{ ...indexed1, b: 11 } : { b: number; a: number; }
>i : { [x: string]: number; b: number; a: number; }
>{ ...indexed1, b: 11 } : { [x: string]: number; b: number; a: number; }
>indexed1 : { [n: string]: number; a: number; }
>b : number
>11 : 11

// only indexed has indexer, so i[101]: any
i[101];
>i[101] : any
>i : { b: number; a: number; }
>i[101] : number
>i : { [x: string]: number; b: number; a: number; }
>101 : 101

let ii = { ...indexed1, ...indexed2 };
Expand All @@ -42,9 +46,9 @@ declare const b: boolean;
>b : boolean

indexed3 = { ...b ? indexed3 : undefined };
>indexed3 = { ...b ? indexed3 : undefined } : {} | { [n: string]: number; }
>indexed3 = { ...b ? indexed3 : undefined } : {} | { [x: string]: number; }
>indexed3 : { [n: string]: number; }
>{ ...b ? indexed3 : undefined } : {} | { [n: string]: number; }
>{ ...b ? indexed3 : undefined } : {} | { [x: string]: number; }
>b ? indexed3 : undefined : { [n: string]: number; } | undefined
>b : boolean
>indexed3 : { [n: string]: number; }
Expand All @@ -66,3 +70,85 @@ writable.a = 0; // should be ok.
>a : number
>0 : 0

var mixed = { foo: true, ...indexed3, bar: 'bar' };
>mixed : { [x: string]: string | number | boolean; bar: string; foo: boolean; }
>{ foo: true, ...indexed3, bar: 'bar' } : { [x: string]: string | number | boolean; bar: string; foo: boolean; }
>foo : boolean
>true : true
>indexed3 : { [n: string]: number; }
>bar : string
>'bar' : "bar"

mixed.foo; // boolean
>mixed.foo : boolean
>mixed : { [x: string]: string | number | boolean; bar: string; foo: boolean; }
>foo : boolean

mixed.bar; // string
>mixed.bar : string
>mixed : { [x: string]: string | number | boolean; bar: string; foo: boolean; }
>bar : string

mixed.baz; // string | number | boolean
>mixed.baz : string | number | boolean
>mixed : { [x: string]: string | number | boolean; bar: string; foo: boolean; }
>baz : string | number | boolean

var mixed2 = { foo: true, ...indexed4, bar: 'bar' };
>mixed2 : { [x: number]: number; bar: string; foo: boolean; }
>{ foo: true, ...indexed4, bar: 'bar' } : { [x: number]: number; bar: string; foo: boolean; }
>foo : boolean
>true : true
>indexed4 : { [n: number]: number; }
>bar : string
>'bar' : "bar"

mixed2.foo; // boolean
>mixed2.foo : boolean
>mixed2 : { [x: number]: number; bar: string; foo: boolean; }
>foo : boolean

mixed2.bar; // string
>mixed2.bar : string
>mixed2 : { [x: number]: number; bar: string; foo: boolean; }
>bar : string

mixed2[1]; // number
>mixed2[1] : number
>mixed2 : { [x: number]: number; bar: string; foo: boolean; }
>1 : 1

var mixed3 = { ...indexed4, '1': 'foo'};
>mixed3 : { [x: number]: string | number; '1': string; }
>{ ...indexed4, '1': 'foo'} : { [x: number]: string | number; '1': string; }
>indexed4 : { [n: number]: number; }
>'1' : string
>'foo' : "foo"

mixed3[0]; // string | number
>mixed3[0] : string | number
>mixed3 : { [x: number]: string | number; '1': string; }
>0 : 0

mixed3[1]; // string
>mixed3[1] : string
>mixed3 : { [x: number]: string | number; '1': string; }
>1 : 1

var mixed4 = { ...indexed3, '1': 'foo'};
>mixed4 : { [x: string]: string | number; '1': string; }
>{ ...indexed3, '1': 'foo'} : { [x: string]: string | number; '1': string; }
>indexed3 : { [n: string]: number; }
>'1' : string
>'foo' : "foo"

mixed4.foo; // string | number
>mixed4.foo : string | number
>mixed4 : { [x: string]: string | number; '1': string; }
>foo : string | number

mixed4[1]; // string
>mixed4[1] : string
>mixed4 : { [x: string]: string | number; '1': string; }
>1 : 1

0 comments on commit a626e4e

Please sign in to comment.