diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2f9ad3e33041d..acdb6025c2dfa 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18176,7 +18176,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const declarations = concatenate(leftProp.declarations, rightProp.declarations); const flags = SymbolFlags.Property | (leftProp.flags & SymbolFlags.Optional); const result = createSymbol(flags, leftProp.escapedName); - result.links.type = getUnionType([getTypeOfSymbol(leftProp), removeMissingOrUndefinedType(rightType)], UnionReduction.Subtype); + // Optimization: avoid calculating the union type if spreading into the exact same type. + // This is common, e.g. spreading one options bag into another where the bags have the + // same type, or have properties which overlap. If the unions are large, it may turn out + // to be expensive to perform subtype reduction. + const leftType = getTypeOfSymbol(leftProp); + const leftTypeWithoutUndefined = removeMissingOrUndefinedType(leftType); + const rightTypeWithoutUndefined = removeMissingOrUndefinedType(rightType); + result.links.type = leftTypeWithoutUndefined === rightTypeWithoutUndefined ? leftType : getUnionType([leftType, rightTypeWithoutUndefined], UnionReduction.Subtype); result.links.leftSpread = leftProp; result.links.rightSpread = rightProp; result.declarations = declarations; diff --git a/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=false).js b/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=false).js new file mode 100644 index 0000000000000..98964c65cab8b --- /dev/null +++ b/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=false).js @@ -0,0 +1,50 @@ +//// [spreadObjectPermutations.ts] +declare const a: { x: string | number }; +declare const b: { x?: string | number }; +declare const c: { x?: string | number | undefined }; + +const v_a = { ...a }; +const v_b = { ...b }; +const v_c = { ...c }; +const v_ab = { ...a, ...b }; +const v_ac = { ...a, ...c }; +const v_ba = { ...b, ...a }; +const v_bc = { ...b, ...c }; +const v_ca = { ...c, ...a }; +const v_cb = { ...c, ...b }; +const v_abc = { ...a, ...b, ...c }; +const v_acb = { ...a, ...c, ...b }; +const v_bac = { ...b, ...a, ...c }; +const v_bca = { ...b, ...c, ...a }; +const v_cab = { ...c, ...a, ...b }; +const v_cba = { ...c, ...b, ...a }; + + +//// [spreadObjectPermutations.js] +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var v_a = __assign({}, a); +var v_b = __assign({}, b); +var v_c = __assign({}, c); +var v_ab = __assign(__assign({}, a), b); +var v_ac = __assign(__assign({}, a), c); +var v_ba = __assign(__assign({}, b), a); +var v_bc = __assign(__assign({}, b), c); +var v_ca = __assign(__assign({}, c), a); +var v_cb = __assign(__assign({}, c), b); +var v_abc = __assign(__assign(__assign({}, a), b), c); +var v_acb = __assign(__assign(__assign({}, a), c), b); +var v_bac = __assign(__assign(__assign({}, b), a), c); +var v_bca = __assign(__assign(__assign({}, b), c), a); +var v_cab = __assign(__assign(__assign({}, c), a), b); +var v_cba = __assign(__assign(__assign({}, c), b), a); diff --git a/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=false).symbols b/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=false).symbols new file mode 100644 index 0000000000000..cc1b53acb7033 --- /dev/null +++ b/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=false).symbols @@ -0,0 +1,91 @@ +=== tests/cases/compiler/spreadObjectPermutations.ts === +declare const a: { x: string | number }; +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) +>x : Symbol(x, Decl(spreadObjectPermutations.ts, 0, 18)) + +declare const b: { x?: string | number }; +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) +>x : Symbol(x, Decl(spreadObjectPermutations.ts, 1, 18)) + +declare const c: { x?: string | number | undefined }; +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) +>x : Symbol(x, Decl(spreadObjectPermutations.ts, 2, 18)) + +const v_a = { ...a }; +>v_a : Symbol(v_a, Decl(spreadObjectPermutations.ts, 4, 5)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) + +const v_b = { ...b }; +>v_b : Symbol(v_b, Decl(spreadObjectPermutations.ts, 5, 5)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) + +const v_c = { ...c }; +>v_c : Symbol(v_c, Decl(spreadObjectPermutations.ts, 6, 5)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) + +const v_ab = { ...a, ...b }; +>v_ab : Symbol(v_ab, Decl(spreadObjectPermutations.ts, 7, 5)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) + +const v_ac = { ...a, ...c }; +>v_ac : Symbol(v_ac, Decl(spreadObjectPermutations.ts, 8, 5)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) + +const v_ba = { ...b, ...a }; +>v_ba : Symbol(v_ba, Decl(spreadObjectPermutations.ts, 9, 5)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) + +const v_bc = { ...b, ...c }; +>v_bc : Symbol(v_bc, Decl(spreadObjectPermutations.ts, 10, 5)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) + +const v_ca = { ...c, ...a }; +>v_ca : Symbol(v_ca, Decl(spreadObjectPermutations.ts, 11, 5)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) + +const v_cb = { ...c, ...b }; +>v_cb : Symbol(v_cb, Decl(spreadObjectPermutations.ts, 12, 5)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) + +const v_abc = { ...a, ...b, ...c }; +>v_abc : Symbol(v_abc, Decl(spreadObjectPermutations.ts, 13, 5)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) + +const v_acb = { ...a, ...c, ...b }; +>v_acb : Symbol(v_acb, Decl(spreadObjectPermutations.ts, 14, 5)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) + +const v_bac = { ...b, ...a, ...c }; +>v_bac : Symbol(v_bac, Decl(spreadObjectPermutations.ts, 15, 5)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) + +const v_bca = { ...b, ...c, ...a }; +>v_bca : Symbol(v_bca, Decl(spreadObjectPermutations.ts, 16, 5)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) + +const v_cab = { ...c, ...a, ...b }; +>v_cab : Symbol(v_cab, Decl(spreadObjectPermutations.ts, 17, 5)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) + +const v_cba = { ...c, ...b, ...a }; +>v_cba : Symbol(v_cba, Decl(spreadObjectPermutations.ts, 18, 5)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) + diff --git a/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=false).types b/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=false).types new file mode 100644 index 0000000000000..cd47d89594167 --- /dev/null +++ b/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=false).types @@ -0,0 +1,106 @@ +=== tests/cases/compiler/spreadObjectPermutations.ts === +declare const a: { x: string | number }; +>a : { x: string | number; } +>x : string | number + +declare const b: { x?: string | number }; +>b : { x?: string | number | undefined; } +>x : string | number | undefined + +declare const c: { x?: string | number | undefined }; +>c : { x?: string | number | undefined; } +>x : string | number | undefined + +const v_a = { ...a }; +>v_a : { x: string | number; } +>{ ...a } : { x: string | number; } +>a : { x: string | number; } + +const v_b = { ...b }; +>v_b : { x?: string | number | undefined; } +>{ ...b } : { x?: string | number | undefined; } +>b : { x?: string | number | undefined; } + +const v_c = { ...c }; +>v_c : { x?: string | number | undefined; } +>{ ...c } : { x?: string | number | undefined; } +>c : { x?: string | number | undefined; } + +const v_ab = { ...a, ...b }; +>v_ab : { x: string | number; } +>{ ...a, ...b } : { x: string | number; } +>a : { x: string | number; } +>b : { x?: string | number | undefined; } + +const v_ac = { ...a, ...c }; +>v_ac : { x: string | number; } +>{ ...a, ...c } : { x: string | number; } +>a : { x: string | number; } +>c : { x?: string | number | undefined; } + +const v_ba = { ...b, ...a }; +>v_ba : { x: string | number; } +>{ ...b, ...a } : { x: string | number; } +>b : { x?: string | number | undefined; } +>a : { x: string | number; } + +const v_bc = { ...b, ...c }; +>v_bc : { x?: string | number | undefined; } +>{ ...b, ...c } : { x?: string | number | undefined; } +>b : { x?: string | number | undefined; } +>c : { x?: string | number | undefined; } + +const v_ca = { ...c, ...a }; +>v_ca : { x: string | number; } +>{ ...c, ...a } : { x: string | number; } +>c : { x?: string | number | undefined; } +>a : { x: string | number; } + +const v_cb = { ...c, ...b }; +>v_cb : { x?: string | number | undefined; } +>{ ...c, ...b } : { x?: string | number | undefined; } +>c : { x?: string | number | undefined; } +>b : { x?: string | number | undefined; } + +const v_abc = { ...a, ...b, ...c }; +>v_abc : { x: string | number; } +>{ ...a, ...b, ...c } : { x: string | number; } +>a : { x: string | number; } +>b : { x?: string | number | undefined; } +>c : { x?: string | number | undefined; } + +const v_acb = { ...a, ...c, ...b }; +>v_acb : { x: string | number; } +>{ ...a, ...c, ...b } : { x: string | number; } +>a : { x: string | number; } +>c : { x?: string | number | undefined; } +>b : { x?: string | number | undefined; } + +const v_bac = { ...b, ...a, ...c }; +>v_bac : { x: string | number; } +>{ ...b, ...a, ...c } : { x: string | number; } +>b : { x?: string | number | undefined; } +>a : { x: string | number; } +>c : { x?: string | number | undefined; } + +const v_bca = { ...b, ...c, ...a }; +>v_bca : { x: string | number; } +>{ ...b, ...c, ...a } : { x: string | number; } +>b : { x?: string | number | undefined; } +>c : { x?: string | number | undefined; } +>a : { x: string | number; } + +const v_cab = { ...c, ...a, ...b }; +>v_cab : { x: string | number; } +>{ ...c, ...a, ...b } : { x: string | number; } +>c : { x?: string | number | undefined; } +>a : { x: string | number; } +>b : { x?: string | number | undefined; } + +const v_cba = { ...c, ...b, ...a }; +>v_cba : { x: string | number; } +>{ ...c, ...b, ...a } : { x: string | number; } +>c : { x?: string | number | undefined; } +>b : { x?: string | number | undefined; } +>a : { x: string | number; } + diff --git a/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=true).js b/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=true).js new file mode 100644 index 0000000000000..98964c65cab8b --- /dev/null +++ b/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=true).js @@ -0,0 +1,50 @@ +//// [spreadObjectPermutations.ts] +declare const a: { x: string | number }; +declare const b: { x?: string | number }; +declare const c: { x?: string | number | undefined }; + +const v_a = { ...a }; +const v_b = { ...b }; +const v_c = { ...c }; +const v_ab = { ...a, ...b }; +const v_ac = { ...a, ...c }; +const v_ba = { ...b, ...a }; +const v_bc = { ...b, ...c }; +const v_ca = { ...c, ...a }; +const v_cb = { ...c, ...b }; +const v_abc = { ...a, ...b, ...c }; +const v_acb = { ...a, ...c, ...b }; +const v_bac = { ...b, ...a, ...c }; +const v_bca = { ...b, ...c, ...a }; +const v_cab = { ...c, ...a, ...b }; +const v_cba = { ...c, ...b, ...a }; + + +//// [spreadObjectPermutations.js] +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var v_a = __assign({}, a); +var v_b = __assign({}, b); +var v_c = __assign({}, c); +var v_ab = __assign(__assign({}, a), b); +var v_ac = __assign(__assign({}, a), c); +var v_ba = __assign(__assign({}, b), a); +var v_bc = __assign(__assign({}, b), c); +var v_ca = __assign(__assign({}, c), a); +var v_cb = __assign(__assign({}, c), b); +var v_abc = __assign(__assign(__assign({}, a), b), c); +var v_acb = __assign(__assign(__assign({}, a), c), b); +var v_bac = __assign(__assign(__assign({}, b), a), c); +var v_bca = __assign(__assign(__assign({}, b), c), a); +var v_cab = __assign(__assign(__assign({}, c), a), b); +var v_cba = __assign(__assign(__assign({}, c), b), a); diff --git a/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=true).symbols b/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=true).symbols new file mode 100644 index 0000000000000..cc1b53acb7033 --- /dev/null +++ b/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=true).symbols @@ -0,0 +1,91 @@ +=== tests/cases/compiler/spreadObjectPermutations.ts === +declare const a: { x: string | number }; +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) +>x : Symbol(x, Decl(spreadObjectPermutations.ts, 0, 18)) + +declare const b: { x?: string | number }; +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) +>x : Symbol(x, Decl(spreadObjectPermutations.ts, 1, 18)) + +declare const c: { x?: string | number | undefined }; +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) +>x : Symbol(x, Decl(spreadObjectPermutations.ts, 2, 18)) + +const v_a = { ...a }; +>v_a : Symbol(v_a, Decl(spreadObjectPermutations.ts, 4, 5)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) + +const v_b = { ...b }; +>v_b : Symbol(v_b, Decl(spreadObjectPermutations.ts, 5, 5)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) + +const v_c = { ...c }; +>v_c : Symbol(v_c, Decl(spreadObjectPermutations.ts, 6, 5)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) + +const v_ab = { ...a, ...b }; +>v_ab : Symbol(v_ab, Decl(spreadObjectPermutations.ts, 7, 5)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) + +const v_ac = { ...a, ...c }; +>v_ac : Symbol(v_ac, Decl(spreadObjectPermutations.ts, 8, 5)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) + +const v_ba = { ...b, ...a }; +>v_ba : Symbol(v_ba, Decl(spreadObjectPermutations.ts, 9, 5)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) + +const v_bc = { ...b, ...c }; +>v_bc : Symbol(v_bc, Decl(spreadObjectPermutations.ts, 10, 5)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) + +const v_ca = { ...c, ...a }; +>v_ca : Symbol(v_ca, Decl(spreadObjectPermutations.ts, 11, 5)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) + +const v_cb = { ...c, ...b }; +>v_cb : Symbol(v_cb, Decl(spreadObjectPermutations.ts, 12, 5)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) + +const v_abc = { ...a, ...b, ...c }; +>v_abc : Symbol(v_abc, Decl(spreadObjectPermutations.ts, 13, 5)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) + +const v_acb = { ...a, ...c, ...b }; +>v_acb : Symbol(v_acb, Decl(spreadObjectPermutations.ts, 14, 5)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) + +const v_bac = { ...b, ...a, ...c }; +>v_bac : Symbol(v_bac, Decl(spreadObjectPermutations.ts, 15, 5)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) + +const v_bca = { ...b, ...c, ...a }; +>v_bca : Symbol(v_bca, Decl(spreadObjectPermutations.ts, 16, 5)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) + +const v_cab = { ...c, ...a, ...b }; +>v_cab : Symbol(v_cab, Decl(spreadObjectPermutations.ts, 17, 5)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) + +const v_cba = { ...c, ...b, ...a }; +>v_cba : Symbol(v_cba, Decl(spreadObjectPermutations.ts, 18, 5)) +>c : Symbol(c, Decl(spreadObjectPermutations.ts, 2, 13)) +>b : Symbol(b, Decl(spreadObjectPermutations.ts, 1, 13)) +>a : Symbol(a, Decl(spreadObjectPermutations.ts, 0, 13)) + diff --git a/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=true).types b/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=true).types new file mode 100644 index 0000000000000..58332782b0335 --- /dev/null +++ b/tests/baselines/reference/spreadObjectPermutations(exactoptionalpropertytypes=true).types @@ -0,0 +1,106 @@ +=== tests/cases/compiler/spreadObjectPermutations.ts === +declare const a: { x: string | number }; +>a : { x: string | number; } +>x : string | number + +declare const b: { x?: string | number }; +>b : { x?: string | number; } +>x : string | number | undefined + +declare const c: { x?: string | number | undefined }; +>c : { x?: string | number | undefined; } +>x : string | number | undefined + +const v_a = { ...a }; +>v_a : { x: string | number; } +>{ ...a } : { x: string | number; } +>a : { x: string | number; } + +const v_b = { ...b }; +>v_b : { x?: string | number; } +>{ ...b } : { x?: string | number; } +>b : { x?: string | number; } + +const v_c = { ...c }; +>v_c : { x?: string | number | undefined; } +>{ ...c } : { x?: string | number | undefined; } +>c : { x?: string | number | undefined; } + +const v_ab = { ...a, ...b }; +>v_ab : { x: string | number; } +>{ ...a, ...b } : { x: string | number; } +>a : { x: string | number; } +>b : { x?: string | number; } + +const v_ac = { ...a, ...c }; +>v_ac : { x: string | number | undefined; } +>{ ...a, ...c } : { x: string | number | undefined; } +>a : { x: string | number; } +>c : { x?: string | number | undefined; } + +const v_ba = { ...b, ...a }; +>v_ba : { x: string | number; } +>{ ...b, ...a } : { x: string | number; } +>b : { x?: string | number; } +>a : { x: string | number; } + +const v_bc = { ...b, ...c }; +>v_bc : { x?: string | number | undefined; } +>{ ...b, ...c } : { x?: string | number | undefined; } +>b : { x?: string | number; } +>c : { x?: string | number | undefined; } + +const v_ca = { ...c, ...a }; +>v_ca : { x: string | number; } +>{ ...c, ...a } : { x: string | number; } +>c : { x?: string | number | undefined; } +>a : { x: string | number; } + +const v_cb = { ...c, ...b }; +>v_cb : { x?: string | number | undefined; } +>{ ...c, ...b } : { x?: string | number | undefined; } +>c : { x?: string | number | undefined; } +>b : { x?: string | number; } + +const v_abc = { ...a, ...b, ...c }; +>v_abc : { x: string | number | undefined; } +>{ ...a, ...b, ...c } : { x: string | number | undefined; } +>a : { x: string | number; } +>b : { x?: string | number; } +>c : { x?: string | number | undefined; } + +const v_acb = { ...a, ...c, ...b }; +>v_acb : { x: string | number | undefined; } +>{ ...a, ...c, ...b } : { x: string | number | undefined; } +>a : { x: string | number; } +>c : { x?: string | number | undefined; } +>b : { x?: string | number; } + +const v_bac = { ...b, ...a, ...c }; +>v_bac : { x: string | number | undefined; } +>{ ...b, ...a, ...c } : { x: string | number | undefined; } +>b : { x?: string | number; } +>a : { x: string | number; } +>c : { x?: string | number | undefined; } + +const v_bca = { ...b, ...c, ...a }; +>v_bca : { x: string | number; } +>{ ...b, ...c, ...a } : { x: string | number; } +>b : { x?: string | number; } +>c : { x?: string | number | undefined; } +>a : { x: string | number; } + +const v_cab = { ...c, ...a, ...b }; +>v_cab : { x: string | number; } +>{ ...c, ...a, ...b } : { x: string | number; } +>c : { x?: string | number | undefined; } +>a : { x: string | number; } +>b : { x?: string | number; } + +const v_cba = { ...c, ...b, ...a }; +>v_cba : { x: string | number; } +>{ ...c, ...b, ...a } : { x: string | number; } +>c : { x?: string | number | undefined; } +>b : { x?: string | number; } +>a : { x: string | number; } + diff --git a/tests/cases/compiler/spreadObjectPermutations.ts b/tests/cases/compiler/spreadObjectPermutations.ts new file mode 100644 index 0000000000000..c047601c31d1b --- /dev/null +++ b/tests/cases/compiler/spreadObjectPermutations.ts @@ -0,0 +1,23 @@ +// @strict: true +// @exactOptionalPropertyTypes: false, true + + +declare const a: { x: string | number }; +declare const b: { x?: string | number }; +declare const c: { x?: string | number | undefined }; + +const v_a = { ...a }; +const v_b = { ...b }; +const v_c = { ...c }; +const v_ab = { ...a, ...b }; +const v_ac = { ...a, ...c }; +const v_ba = { ...b, ...a }; +const v_bc = { ...b, ...c }; +const v_ca = { ...c, ...a }; +const v_cb = { ...c, ...b }; +const v_abc = { ...a, ...b, ...c }; +const v_acb = { ...a, ...c, ...b }; +const v_bac = { ...b, ...a, ...c }; +const v_bca = { ...b, ...c, ...a }; +const v_cab = { ...c, ...a, ...b }; +const v_cba = { ...c, ...b, ...a };