Skip to content

Commit a55ed26

Browse files
committed
Spread any types to any
1 parent 7a2c7ad commit a55ed26

6 files changed

Lines changed: 95 additions & 74 deletions

File tree

src/compiler/checker.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5884,8 +5884,11 @@ namespace ts {
58845884
* this function should be called in a left folding style, with left = previous result of getSpreadType
58855885
* and right = the new element to be spread.
58865886
*/
5887-
function getSpreadType(left: Type, right: Type, symbol: Symbol): ResolvedType {
5888-
Debug.assert(!!(left.flags & TypeFlags.Object) && !!(right.flags & TypeFlags.Object), "Only object types may be spread.");
5887+
function getSpreadType(left: Type, right: Type, symbol: Symbol): ResolvedType | IntrinsicType {
5888+
Debug.assert(!!(left.flags & (TypeFlags.Object | TypeFlags.Any)) && !!(right.flags & (TypeFlags.Object | TypeFlags.Any)), "Only object types may be spread.");
5889+
if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) {
5890+
return anyType;
5891+
}
58895892
const members = createMap<Symbol>();
58905893
const skippedPrivateMembers = createMap<boolean>();
58915894
let stringIndexInfo: IndexInfo;
@@ -10934,7 +10937,7 @@ namespace ts {
1093410937
typeFlags = 0;
1093510938
}
1093610939
const type = checkExpression((memberDecl as SpreadElementExpression).expression);
10937-
if (!(type.flags & TypeFlags.Object)) {
10940+
if (!(type.flags & (TypeFlags.Object | TypeFlags.Any))) {
1093810941
error(memberDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types);
1093910942
return unknownType;
1094010943
}

tests/baselines/reference/objectSpread.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ getter.a = 12;
3838
// functions result in { }
3939
let spreadFunc = { ...(function () { }) };
4040

41+
// any results in any
42+
let anything: any;
43+
let spreadAny = { ...anything };
44+
4145
// methods are not enumerable
4246
class C { p = 1; m() { } }
4347
let c: C = new C()
@@ -109,6 +113,9 @@ var getter = __assign({}, op, { c: 7 });
109113
getter.a = 12;
110114
// functions result in { }
111115
var spreadFunc = __assign({}, (function () { }));
116+
// any results in any
117+
var anything;
118+
var spreadAny = __assign({}, anything);
112119
// methods are not enumerable
113120
var C = (function () {
114121
function C() {

tests/baselines/reference/objectSpread.symbols

Lines changed: 68 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -154,123 +154,130 @@ getter.a = 12;
154154
let spreadFunc = { ...(function () { }) };
155155
>spreadFunc : Symbol(spreadFunc, Decl(objectSpread.ts, 37, 3))
156156

157+
// any results in any
158+
let anything: any;
159+
>anything : Symbol(anything, Decl(objectSpread.ts, 40, 3))
160+
161+
let spreadAny = { ...anything };
162+
>spreadAny : Symbol(spreadAny, Decl(objectSpread.ts, 41, 3))
163+
157164
// methods are not enumerable
158165
class C { p = 1; m() { } }
159-
>C : Symbol(C, Decl(objectSpread.ts, 37, 42))
160-
>p : Symbol(C.p, Decl(objectSpread.ts, 40, 9))
161-
>m : Symbol(C.m, Decl(objectSpread.ts, 40, 16))
166+
>C : Symbol(C, Decl(objectSpread.ts, 41, 32))
167+
>p : Symbol(C.p, Decl(objectSpread.ts, 44, 9))
168+
>m : Symbol(C.m, Decl(objectSpread.ts, 44, 16))
162169

163170
let c: C = new C()
164-
>c : Symbol(c, Decl(objectSpread.ts, 41, 3))
165-
>C : Symbol(C, Decl(objectSpread.ts, 37, 42))
166-
>C : Symbol(C, Decl(objectSpread.ts, 37, 42))
171+
>c : Symbol(c, Decl(objectSpread.ts, 45, 3))
172+
>C : Symbol(C, Decl(objectSpread.ts, 41, 32))
173+
>C : Symbol(C, Decl(objectSpread.ts, 41, 32))
167174

168175
let spreadC: { p: number } = { ...c }
169-
>spreadC : Symbol(spreadC, Decl(objectSpread.ts, 42, 3))
170-
>p : Symbol(p, Decl(objectSpread.ts, 42, 14))
176+
>spreadC : Symbol(spreadC, Decl(objectSpread.ts, 46, 3))
177+
>p : Symbol(p, Decl(objectSpread.ts, 46, 14))
171178

172179
// own methods are enumerable
173180
let cplus: { p: number, plus(): void } = { ...c, plus() { return this.p + 1; } };
174-
>cplus : Symbol(cplus, Decl(objectSpread.ts, 45, 3))
175-
>p : Symbol(p, Decl(objectSpread.ts, 45, 12))
176-
>plus : Symbol(plus, Decl(objectSpread.ts, 45, 23))
177-
>plus : Symbol(plus, Decl(objectSpread.ts, 45, 48))
181+
>cplus : Symbol(cplus, Decl(objectSpread.ts, 49, 3))
182+
>p : Symbol(p, Decl(objectSpread.ts, 49, 12))
183+
>plus : Symbol(plus, Decl(objectSpread.ts, 49, 23))
184+
>plus : Symbol(plus, Decl(objectSpread.ts, 49, 48))
178185

179186
cplus.plus();
180-
>cplus.plus : Symbol(plus, Decl(objectSpread.ts, 45, 23))
181-
>cplus : Symbol(cplus, Decl(objectSpread.ts, 45, 3))
182-
>plus : Symbol(plus, Decl(objectSpread.ts, 45, 23))
187+
>cplus.plus : Symbol(plus, Decl(objectSpread.ts, 49, 23))
188+
>cplus : Symbol(cplus, Decl(objectSpread.ts, 49, 3))
189+
>plus : Symbol(plus, Decl(objectSpread.ts, 49, 23))
183190

184191
// new field's type conflicting with existing field is OK
185192
let changeTypeAfter: { a: string, b: string } =
186-
>changeTypeAfter : Symbol(changeTypeAfter, Decl(objectSpread.ts, 49, 3))
187-
>a : Symbol(a, Decl(objectSpread.ts, 49, 22))
188-
>b : Symbol(b, Decl(objectSpread.ts, 49, 33))
193+
>changeTypeAfter : Symbol(changeTypeAfter, Decl(objectSpread.ts, 53, 3))
194+
>a : Symbol(a, Decl(objectSpread.ts, 53, 22))
195+
>b : Symbol(b, Decl(objectSpread.ts, 53, 33))
189196

190197
{ ...o, a: 'wrong type?' }
191-
>a : Symbol(a, Decl(objectSpread.ts, 50, 11))
198+
>a : Symbol(a, Decl(objectSpread.ts, 54, 11))
192199

193200
let changeTypeBefore: { a: number, b: string } =
194-
>changeTypeBefore : Symbol(changeTypeBefore, Decl(objectSpread.ts, 51, 3))
195-
>a : Symbol(a, Decl(objectSpread.ts, 51, 23))
196-
>b : Symbol(b, Decl(objectSpread.ts, 51, 34))
201+
>changeTypeBefore : Symbol(changeTypeBefore, Decl(objectSpread.ts, 55, 3))
202+
>a : Symbol(a, Decl(objectSpread.ts, 55, 23))
203+
>b : Symbol(b, Decl(objectSpread.ts, 55, 34))
197204

198205
{ a: 'wrong type?', ...o };
199-
>a : Symbol(a, Decl(objectSpread.ts, 52, 5))
206+
>a : Symbol(a, Decl(objectSpread.ts, 56, 5))
200207

201208
let changeTypeBoth: { a: string, b: number } =
202-
>changeTypeBoth : Symbol(changeTypeBoth, Decl(objectSpread.ts, 53, 3))
203-
>a : Symbol(a, Decl(objectSpread.ts, 53, 21))
204-
>b : Symbol(b, Decl(objectSpread.ts, 53, 32))
209+
>changeTypeBoth : Symbol(changeTypeBoth, Decl(objectSpread.ts, 57, 3))
210+
>a : Symbol(a, Decl(objectSpread.ts, 57, 21))
211+
>b : Symbol(b, Decl(objectSpread.ts, 57, 32))
205212

206213
{ ...o, ...swap };
207214

208215
// optional
209216
let definiteBoolean: { sn: boolean };
210-
>definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 57, 3))
211-
>sn : Symbol(sn, Decl(objectSpread.ts, 57, 22))
217+
>definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 61, 3))
218+
>sn : Symbol(sn, Decl(objectSpread.ts, 61, 22))
212219

213220
let definiteString: { sn: string };
214-
>definiteString : Symbol(definiteString, Decl(objectSpread.ts, 58, 3))
215-
>sn : Symbol(sn, Decl(objectSpread.ts, 58, 21))
221+
>definiteString : Symbol(definiteString, Decl(objectSpread.ts, 62, 3))
222+
>sn : Symbol(sn, Decl(objectSpread.ts, 62, 21))
216223

217224
let optionalString: { sn?: string };
218-
>optionalString : Symbol(optionalString, Decl(objectSpread.ts, 59, 3))
219-
>sn : Symbol(sn, Decl(objectSpread.ts, 59, 21))
225+
>optionalString : Symbol(optionalString, Decl(objectSpread.ts, 63, 3))
226+
>sn : Symbol(sn, Decl(objectSpread.ts, 63, 21))
220227

221228
let optionalNumber: { sn?: number };
222-
>optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 60, 3))
223-
>sn : Symbol(sn, Decl(objectSpread.ts, 60, 21))
229+
>optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 64, 3))
230+
>sn : Symbol(sn, Decl(objectSpread.ts, 64, 21))
224231

225232
let optionalUnionStops: { sn: string | number | boolean } = { ...definiteBoolean, ...definiteString, ...optionalNumber };
226-
>optionalUnionStops : Symbol(optionalUnionStops, Decl(objectSpread.ts, 61, 3))
227-
>sn : Symbol(sn, Decl(objectSpread.ts, 61, 25))
233+
>optionalUnionStops : Symbol(optionalUnionStops, Decl(objectSpread.ts, 65, 3))
234+
>sn : Symbol(sn, Decl(objectSpread.ts, 65, 25))
228235

229236
let optionalUnionDuplicates: { sn: string | number } = { ...definiteBoolean, ...definiteString, ...optionalString, ...optionalNumber };
230-
>optionalUnionDuplicates : Symbol(optionalUnionDuplicates, Decl(objectSpread.ts, 62, 3))
231-
>sn : Symbol(sn, Decl(objectSpread.ts, 62, 30))
237+
>optionalUnionDuplicates : Symbol(optionalUnionDuplicates, Decl(objectSpread.ts, 66, 3))
238+
>sn : Symbol(sn, Decl(objectSpread.ts, 66, 30))
232239

233240
let allOptional: { sn?: string | number } = { ...optionalString, ...optionalNumber };
234-
>allOptional : Symbol(allOptional, Decl(objectSpread.ts, 63, 3))
235-
>sn : Symbol(sn, Decl(objectSpread.ts, 63, 18))
241+
>allOptional : Symbol(allOptional, Decl(objectSpread.ts, 67, 3))
242+
>sn : Symbol(sn, Decl(objectSpread.ts, 67, 18))
236243

237244
// computed property
238245
let computedFirst: { a: number, b: string, "before everything": number } =
239-
>computedFirst : Symbol(computedFirst, Decl(objectSpread.ts, 66, 3))
240-
>a : Symbol(a, Decl(objectSpread.ts, 66, 20))
241-
>b : Symbol(b, Decl(objectSpread.ts, 66, 31))
246+
>computedFirst : Symbol(computedFirst, Decl(objectSpread.ts, 70, 3))
247+
>a : Symbol(a, Decl(objectSpread.ts, 70, 20))
248+
>b : Symbol(b, Decl(objectSpread.ts, 70, 31))
242249

243250
{ ['before everything']: 12, ...o, b: 'yes' }
244-
>'before everything' : Symbol(['before everything'], Decl(objectSpread.ts, 67, 5))
245-
>b : Symbol(b, Decl(objectSpread.ts, 67, 38))
251+
>'before everything' : Symbol(['before everything'], Decl(objectSpread.ts, 71, 5))
252+
>b : Symbol(b, Decl(objectSpread.ts, 71, 38))
246253

247254
let computedMiddle: { a: number, b: string, c: boolean, "in the middle": number } =
248-
>computedMiddle : Symbol(computedMiddle, Decl(objectSpread.ts, 68, 3))
249-
>a : Symbol(a, Decl(objectSpread.ts, 68, 21))
250-
>b : Symbol(b, Decl(objectSpread.ts, 68, 32))
251-
>c : Symbol(c, Decl(objectSpread.ts, 68, 43))
255+
>computedMiddle : Symbol(computedMiddle, Decl(objectSpread.ts, 72, 3))
256+
>a : Symbol(a, Decl(objectSpread.ts, 72, 21))
257+
>b : Symbol(b, Decl(objectSpread.ts, 72, 32))
258+
>c : Symbol(c, Decl(objectSpread.ts, 72, 43))
252259

253260
{ ...o, ['in the middle']: 13, b: 'maybe?', ...o2 }
254-
>'in the middle' : Symbol(['in the middle'], Decl(objectSpread.ts, 69, 11))
255-
>b : Symbol(b, Decl(objectSpread.ts, 69, 34))
261+
>'in the middle' : Symbol(['in the middle'], Decl(objectSpread.ts, 73, 11))
262+
>b : Symbol(b, Decl(objectSpread.ts, 73, 34))
256263

257264
let computedAfter: { a: number, b: string, "at the end": number } =
258-
>computedAfter : Symbol(computedAfter, Decl(objectSpread.ts, 70, 3))
259-
>a : Symbol(a, Decl(objectSpread.ts, 70, 20))
260-
>b : Symbol(b, Decl(objectSpread.ts, 70, 31))
265+
>computedAfter : Symbol(computedAfter, Decl(objectSpread.ts, 74, 3))
266+
>a : Symbol(a, Decl(objectSpread.ts, 74, 20))
267+
>b : Symbol(b, Decl(objectSpread.ts, 74, 31))
261268

262269
{ ...o, b: 'yeah', ['at the end']: 14 }
263-
>b : Symbol(b, Decl(objectSpread.ts, 71, 11))
264-
>'at the end' : Symbol(['at the end'], Decl(objectSpread.ts, 71, 22))
270+
>b : Symbol(b, Decl(objectSpread.ts, 75, 11))
271+
>'at the end' : Symbol(['at the end'], Decl(objectSpread.ts, 75, 22))
265272

266273
// shortcut syntax
267274
let a = 12;
268-
>a : Symbol(a, Decl(objectSpread.ts, 73, 3))
275+
>a : Symbol(a, Decl(objectSpread.ts, 77, 3))
269276

270277
let shortCutted: { a: number, b: string } = { ...o, a }
271-
>shortCutted : Symbol(shortCutted, Decl(objectSpread.ts, 74, 3))
272-
>a : Symbol(a, Decl(objectSpread.ts, 74, 18))
273-
>b : Symbol(b, Decl(objectSpread.ts, 74, 29))
274-
>a : Symbol(a, Decl(objectSpread.ts, 74, 51))
278+
>shortCutted : Symbol(shortCutted, Decl(objectSpread.ts, 78, 3))
279+
>a : Symbol(a, Decl(objectSpread.ts, 78, 18))
280+
>b : Symbol(b, Decl(objectSpread.ts, 78, 29))
281+
>a : Symbol(a, Decl(objectSpread.ts, 78, 51))
275282

276283

tests/baselines/reference/objectSpread.types

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,15 @@ let spreadFunc = { ...(function () { }) };
230230
>(function () { }) : () => void
231231
>function () { } : () => void
232232

233+
// any results in any
234+
let anything: any;
235+
>anything : any
236+
237+
let spreadAny = { ...anything };
238+
>spreadAny : any
239+
>{ ...anything } : any
240+
>anything : any
241+
233242
// methods are not enumerable
234243
class C { p = 1; m() { } }
235244
>C : C

tests/baselines/reference/objectSpreadNegativeParse.errors.txt

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
1-
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(1,12): error TS2698: Spread types may only be created from object types.
21
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(1,15): error TS2304: Cannot find name 'o'.
32
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(1,18): error TS1109: Expression expected.
43
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(2,12): error TS2698: Spread types may only be created from object types.
54
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(2,15): error TS1109: Expression expected.
65
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(2,16): error TS2304: Cannot find name 'o'.
7-
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(3,12): error TS2698: Spread types may only be created from object types.
86
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(3,15): error TS2304: Cannot find name 'matchMedia'.
97
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(3,28): error TS1005: ',' expected.
108
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(3,31): error TS1128: Declaration or statement expected.
11-
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,13): error TS2698: Spread types may only be created from object types.
129
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,16): error TS2304: Cannot find name 'get'.
1310
tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,20): error TS1005: ',' expected.
1411

1512

16-
==== tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts (13 errors) ====
13+
==== tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts (10 errors) ====
1714
let o7 = { ...o? };
18-
~~~~~
19-
!!! error TS2698: Spread types may only be created from object types.
2015
~
2116
!!! error TS2304: Cannot find name 'o'.
2217
~
@@ -29,17 +24,13 @@ tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,20): error T
2924
~
3025
!!! error TS2304: Cannot find name 'o'.
3126
let o9 = { ...matchMedia() { }};
32-
~~~~~~~~~~~~~~~
33-
!!! error TS2698: Spread types may only be created from object types.
3427
~~~~~~~~~~
3528
!!! error TS2304: Cannot find name 'matchMedia'.
3629
~
3730
!!! error TS1005: ',' expected.
3831
~
3932
!!! error TS1128: Declaration or statement expected.
4033
let o10 = { ...get x() { return 12; }};
41-
~~~~~~
42-
!!! error TS2698: Spread types may only be created from object types.
4334
~~~
4435
!!! error TS2304: Cannot find name 'get'.
4536
~

tests/cases/conformance/types/spread/objectSpread.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ getter.a = 12;
3838
// functions result in { }
3939
let spreadFunc = { ...(function () { }) };
4040

41+
// any results in any
42+
let anything: any;
43+
let spreadAny = { ...anything };
44+
4145
// methods are not enumerable
4246
class C { p = 1; m() { } }
4347
let c: C = new C()

0 commit comments

Comments
 (0)