From a55ed26d2be4ac49e6a0b4060eac6ea4ff2333b9 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 4 Nov 2016 16:06:33 -0700 Subject: [PATCH] Spread any types to any --- src/compiler/checker.ts | 9 +- tests/baselines/reference/objectSpread.js | 7 + .../baselines/reference/objectSpread.symbols | 141 +++++++++--------- tests/baselines/reference/objectSpread.types | 9 ++ .../objectSpreadNegativeParse.errors.txt | 11 +- .../conformance/types/spread/objectSpread.ts | 4 + 6 files changed, 101 insertions(+), 80 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3475a9d52c6..20e90f4db25 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5884,8 +5884,11 @@ namespace ts { * this function should be called in a left folding style, with left = previous result of getSpreadType * and right = the new element to be spread. */ - function getSpreadType(left: Type, right: Type, symbol: Symbol): ResolvedType { - Debug.assert(!!(left.flags & TypeFlags.Object) && !!(right.flags & TypeFlags.Object), "Only object types may be spread."); + function getSpreadType(left: Type, right: Type, symbol: Symbol): ResolvedType | IntrinsicType { + Debug.assert(!!(left.flags & (TypeFlags.Object | TypeFlags.Any)) && !!(right.flags & (TypeFlags.Object | TypeFlags.Any)), "Only object types may be spread."); + if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) { + return anyType; + } const members = createMap(); const skippedPrivateMembers = createMap(); let stringIndexInfo: IndexInfo; @@ -10934,7 +10937,7 @@ namespace ts { typeFlags = 0; } const type = checkExpression((memberDecl as SpreadElementExpression).expression); - if (!(type.flags & TypeFlags.Object)) { + if (!(type.flags & (TypeFlags.Object | TypeFlags.Any))) { error(memberDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types); return unknownType; } diff --git a/tests/baselines/reference/objectSpread.js b/tests/baselines/reference/objectSpread.js index c19ead478cb..d1de48c5cab 100644 --- a/tests/baselines/reference/objectSpread.js +++ b/tests/baselines/reference/objectSpread.js @@ -38,6 +38,10 @@ getter.a = 12; // functions result in { } let spreadFunc = { ...(function () { }) }; +// any results in any +let anything: any; +let spreadAny = { ...anything }; + // methods are not enumerable class C { p = 1; m() { } } let c: C = new C() @@ -109,6 +113,9 @@ var getter = __assign({}, op, { c: 7 }); getter.a = 12; // functions result in { } var spreadFunc = __assign({}, (function () { })); +// any results in any +var anything; +var spreadAny = __assign({}, anything); // methods are not enumerable var C = (function () { function C() { diff --git a/tests/baselines/reference/objectSpread.symbols b/tests/baselines/reference/objectSpread.symbols index b95f8273724..4b0a62a5a24 100644 --- a/tests/baselines/reference/objectSpread.symbols +++ b/tests/baselines/reference/objectSpread.symbols @@ -154,123 +154,130 @@ getter.a = 12; let spreadFunc = { ...(function () { }) }; >spreadFunc : Symbol(spreadFunc, Decl(objectSpread.ts, 37, 3)) +// any results in any +let anything: any; +>anything : Symbol(anything, Decl(objectSpread.ts, 40, 3)) + +let spreadAny = { ...anything }; +>spreadAny : Symbol(spreadAny, Decl(objectSpread.ts, 41, 3)) + // methods are not enumerable class C { p = 1; m() { } } ->C : Symbol(C, Decl(objectSpread.ts, 37, 42)) ->p : Symbol(C.p, Decl(objectSpread.ts, 40, 9)) ->m : Symbol(C.m, Decl(objectSpread.ts, 40, 16)) +>C : Symbol(C, Decl(objectSpread.ts, 41, 32)) +>p : Symbol(C.p, Decl(objectSpread.ts, 44, 9)) +>m : Symbol(C.m, Decl(objectSpread.ts, 44, 16)) let c: C = new C() ->c : Symbol(c, Decl(objectSpread.ts, 41, 3)) ->C : Symbol(C, Decl(objectSpread.ts, 37, 42)) ->C : Symbol(C, Decl(objectSpread.ts, 37, 42)) +>c : Symbol(c, Decl(objectSpread.ts, 45, 3)) +>C : Symbol(C, Decl(objectSpread.ts, 41, 32)) +>C : Symbol(C, Decl(objectSpread.ts, 41, 32)) let spreadC: { p: number } = { ...c } ->spreadC : Symbol(spreadC, Decl(objectSpread.ts, 42, 3)) ->p : Symbol(p, Decl(objectSpread.ts, 42, 14)) +>spreadC : Symbol(spreadC, Decl(objectSpread.ts, 46, 3)) +>p : Symbol(p, Decl(objectSpread.ts, 46, 14)) // own methods are enumerable let cplus: { p: number, plus(): void } = { ...c, plus() { return this.p + 1; } }; ->cplus : Symbol(cplus, Decl(objectSpread.ts, 45, 3)) ->p : Symbol(p, Decl(objectSpread.ts, 45, 12)) ->plus : Symbol(plus, Decl(objectSpread.ts, 45, 23)) ->plus : Symbol(plus, Decl(objectSpread.ts, 45, 48)) +>cplus : Symbol(cplus, Decl(objectSpread.ts, 49, 3)) +>p : Symbol(p, Decl(objectSpread.ts, 49, 12)) +>plus : Symbol(plus, Decl(objectSpread.ts, 49, 23)) +>plus : Symbol(plus, Decl(objectSpread.ts, 49, 48)) cplus.plus(); ->cplus.plus : Symbol(plus, Decl(objectSpread.ts, 45, 23)) ->cplus : Symbol(cplus, Decl(objectSpread.ts, 45, 3)) ->plus : Symbol(plus, Decl(objectSpread.ts, 45, 23)) +>cplus.plus : Symbol(plus, Decl(objectSpread.ts, 49, 23)) +>cplus : Symbol(cplus, Decl(objectSpread.ts, 49, 3)) +>plus : Symbol(plus, Decl(objectSpread.ts, 49, 23)) // new field's type conflicting with existing field is OK let changeTypeAfter: { a: string, b: string } = ->changeTypeAfter : Symbol(changeTypeAfter, Decl(objectSpread.ts, 49, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 49, 22)) ->b : Symbol(b, Decl(objectSpread.ts, 49, 33)) +>changeTypeAfter : Symbol(changeTypeAfter, Decl(objectSpread.ts, 53, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 53, 22)) +>b : Symbol(b, Decl(objectSpread.ts, 53, 33)) { ...o, a: 'wrong type?' } ->a : Symbol(a, Decl(objectSpread.ts, 50, 11)) +>a : Symbol(a, Decl(objectSpread.ts, 54, 11)) let changeTypeBefore: { a: number, b: string } = ->changeTypeBefore : Symbol(changeTypeBefore, Decl(objectSpread.ts, 51, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 51, 23)) ->b : Symbol(b, Decl(objectSpread.ts, 51, 34)) +>changeTypeBefore : Symbol(changeTypeBefore, Decl(objectSpread.ts, 55, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 55, 23)) +>b : Symbol(b, Decl(objectSpread.ts, 55, 34)) { a: 'wrong type?', ...o }; ->a : Symbol(a, Decl(objectSpread.ts, 52, 5)) +>a : Symbol(a, Decl(objectSpread.ts, 56, 5)) let changeTypeBoth: { a: string, b: number } = ->changeTypeBoth : Symbol(changeTypeBoth, Decl(objectSpread.ts, 53, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 53, 21)) ->b : Symbol(b, Decl(objectSpread.ts, 53, 32)) +>changeTypeBoth : Symbol(changeTypeBoth, Decl(objectSpread.ts, 57, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 57, 21)) +>b : Symbol(b, Decl(objectSpread.ts, 57, 32)) { ...o, ...swap }; // optional let definiteBoolean: { sn: boolean }; ->definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 57, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 57, 22)) +>definiteBoolean : Symbol(definiteBoolean, Decl(objectSpread.ts, 61, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 61, 22)) let definiteString: { sn: string }; ->definiteString : Symbol(definiteString, Decl(objectSpread.ts, 58, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 58, 21)) +>definiteString : Symbol(definiteString, Decl(objectSpread.ts, 62, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 62, 21)) let optionalString: { sn?: string }; ->optionalString : Symbol(optionalString, Decl(objectSpread.ts, 59, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 59, 21)) +>optionalString : Symbol(optionalString, Decl(objectSpread.ts, 63, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 63, 21)) let optionalNumber: { sn?: number }; ->optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 60, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 60, 21)) +>optionalNumber : Symbol(optionalNumber, Decl(objectSpread.ts, 64, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 64, 21)) let optionalUnionStops: { sn: string | number | boolean } = { ...definiteBoolean, ...definiteString, ...optionalNumber }; ->optionalUnionStops : Symbol(optionalUnionStops, Decl(objectSpread.ts, 61, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 61, 25)) +>optionalUnionStops : Symbol(optionalUnionStops, Decl(objectSpread.ts, 65, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 65, 25)) let optionalUnionDuplicates: { sn: string | number } = { ...definiteBoolean, ...definiteString, ...optionalString, ...optionalNumber }; ->optionalUnionDuplicates : Symbol(optionalUnionDuplicates, Decl(objectSpread.ts, 62, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 62, 30)) +>optionalUnionDuplicates : Symbol(optionalUnionDuplicates, Decl(objectSpread.ts, 66, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 66, 30)) let allOptional: { sn?: string | number } = { ...optionalString, ...optionalNumber }; ->allOptional : Symbol(allOptional, Decl(objectSpread.ts, 63, 3)) ->sn : Symbol(sn, Decl(objectSpread.ts, 63, 18)) +>allOptional : Symbol(allOptional, Decl(objectSpread.ts, 67, 3)) +>sn : Symbol(sn, Decl(objectSpread.ts, 67, 18)) // computed property let computedFirst: { a: number, b: string, "before everything": number } = ->computedFirst : Symbol(computedFirst, Decl(objectSpread.ts, 66, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 66, 20)) ->b : Symbol(b, Decl(objectSpread.ts, 66, 31)) - - { ['before everything']: 12, ...o, b: 'yes' } ->'before everything' : Symbol(['before everything'], Decl(objectSpread.ts, 67, 5)) ->b : Symbol(b, Decl(objectSpread.ts, 67, 38)) - -let computedMiddle: { a: number, b: string, c: boolean, "in the middle": number } = ->computedMiddle : Symbol(computedMiddle, Decl(objectSpread.ts, 68, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 68, 21)) ->b : Symbol(b, Decl(objectSpread.ts, 68, 32)) ->c : Symbol(c, Decl(objectSpread.ts, 68, 43)) - - { ...o, ['in the middle']: 13, b: 'maybe?', ...o2 } ->'in the middle' : Symbol(['in the middle'], Decl(objectSpread.ts, 69, 11)) ->b : Symbol(b, Decl(objectSpread.ts, 69, 34)) - -let computedAfter: { a: number, b: string, "at the end": number } = ->computedAfter : Symbol(computedAfter, Decl(objectSpread.ts, 70, 3)) +>computedFirst : Symbol(computedFirst, Decl(objectSpread.ts, 70, 3)) >a : Symbol(a, Decl(objectSpread.ts, 70, 20)) >b : Symbol(b, Decl(objectSpread.ts, 70, 31)) + { ['before everything']: 12, ...o, b: 'yes' } +>'before everything' : Symbol(['before everything'], Decl(objectSpread.ts, 71, 5)) +>b : Symbol(b, Decl(objectSpread.ts, 71, 38)) + +let computedMiddle: { a: number, b: string, c: boolean, "in the middle": number } = +>computedMiddle : Symbol(computedMiddle, Decl(objectSpread.ts, 72, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 72, 21)) +>b : Symbol(b, Decl(objectSpread.ts, 72, 32)) +>c : Symbol(c, Decl(objectSpread.ts, 72, 43)) + + { ...o, ['in the middle']: 13, b: 'maybe?', ...o2 } +>'in the middle' : Symbol(['in the middle'], Decl(objectSpread.ts, 73, 11)) +>b : Symbol(b, Decl(objectSpread.ts, 73, 34)) + +let computedAfter: { a: number, b: string, "at the end": number } = +>computedAfter : Symbol(computedAfter, Decl(objectSpread.ts, 74, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 74, 20)) +>b : Symbol(b, Decl(objectSpread.ts, 74, 31)) + { ...o, b: 'yeah', ['at the end']: 14 } ->b : Symbol(b, Decl(objectSpread.ts, 71, 11)) ->'at the end' : Symbol(['at the end'], Decl(objectSpread.ts, 71, 22)) +>b : Symbol(b, Decl(objectSpread.ts, 75, 11)) +>'at the end' : Symbol(['at the end'], Decl(objectSpread.ts, 75, 22)) // shortcut syntax let a = 12; ->a : Symbol(a, Decl(objectSpread.ts, 73, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 77, 3)) let shortCutted: { a: number, b: string } = { ...o, a } ->shortCutted : Symbol(shortCutted, Decl(objectSpread.ts, 74, 3)) ->a : Symbol(a, Decl(objectSpread.ts, 74, 18)) ->b : Symbol(b, Decl(objectSpread.ts, 74, 29)) ->a : Symbol(a, Decl(objectSpread.ts, 74, 51)) +>shortCutted : Symbol(shortCutted, Decl(objectSpread.ts, 78, 3)) +>a : Symbol(a, Decl(objectSpread.ts, 78, 18)) +>b : Symbol(b, Decl(objectSpread.ts, 78, 29)) +>a : Symbol(a, Decl(objectSpread.ts, 78, 51)) diff --git a/tests/baselines/reference/objectSpread.types b/tests/baselines/reference/objectSpread.types index e9b9a6421c2..a1c70720d12 100644 --- a/tests/baselines/reference/objectSpread.types +++ b/tests/baselines/reference/objectSpread.types @@ -230,6 +230,15 @@ let spreadFunc = { ...(function () { }) }; >(function () { }) : () => void >function () { } : () => void +// any results in any +let anything: any; +>anything : any + +let spreadAny = { ...anything }; +>spreadAny : any +>{ ...anything } : any +>anything : any + // methods are not enumerable class C { p = 1; m() { } } >C : C diff --git a/tests/baselines/reference/objectSpreadNegativeParse.errors.txt b/tests/baselines/reference/objectSpreadNegativeParse.errors.txt index 987172ef867..b37200c4f02 100644 --- a/tests/baselines/reference/objectSpreadNegativeParse.errors.txt +++ b/tests/baselines/reference/objectSpreadNegativeParse.errors.txt @@ -1,22 +1,17 @@ -tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(1,12): error TS2698: Spread types may only be created from object types. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(1,15): error TS2304: Cannot find name 'o'. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(1,18): error TS1109: Expression expected. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(2,12): error TS2698: Spread types may only be created from object types. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(2,15): error TS1109: Expression expected. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(2,16): error TS2304: Cannot find name 'o'. -tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(3,12): error TS2698: Spread types may only be created from object types. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(3,15): error TS2304: Cannot find name 'matchMedia'. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(3,28): error TS1005: ',' expected. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(3,31): error TS1128: Declaration or statement expected. -tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,13): error TS2698: Spread types may only be created from object types. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,16): error TS2304: Cannot find name 'get'. tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,20): error TS1005: ',' expected. -==== tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts (13 errors) ==== +==== tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts (10 errors) ==== let o7 = { ...o? }; - ~~~~~ -!!! error TS2698: Spread types may only be created from object types. ~ !!! error TS2304: Cannot find name 'o'. ~ @@ -29,8 +24,6 @@ tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,20): error T ~ !!! error TS2304: Cannot find name 'o'. let o9 = { ...matchMedia() { }}; - ~~~~~~~~~~~~~~~ -!!! error TS2698: Spread types may only be created from object types. ~~~~~~~~~~ !!! error TS2304: Cannot find name 'matchMedia'. ~ @@ -38,8 +31,6 @@ tests/cases/conformance/types/spread/objectSpreadNegativeParse.ts(4,20): error T ~ !!! error TS1128: Declaration or statement expected. let o10 = { ...get x() { return 12; }}; - ~~~~~~ -!!! error TS2698: Spread types may only be created from object types. ~~~ !!! error TS2304: Cannot find name 'get'. ~ diff --git a/tests/cases/conformance/types/spread/objectSpread.ts b/tests/cases/conformance/types/spread/objectSpread.ts index 3336196e136..ebf2bdb2ade 100644 --- a/tests/cases/conformance/types/spread/objectSpread.ts +++ b/tests/cases/conformance/types/spread/objectSpread.ts @@ -38,6 +38,10 @@ getter.a = 12; // functions result in { } let spreadFunc = { ...(function () { }) }; +// any results in any +let anything: any; +let spreadAny = { ...anything }; + // methods are not enumerable class C { p = 1; m() { } } let c: C = new C()