Do for unions of many empty-object-spreadables what we did for unions of 2 (#42233)
* Do for unions of many empty-object-spreadables what we did for unions of 2 * Accept baseline
This commit is contained in:
parent
dbba8b358f
commit
11606e4de4
|
@ -14670,19 +14670,18 @@ namespace ts {
|
|||
}
|
||||
|
||||
function tryMergeUnionOfObjectTypeAndEmptyObject(type: UnionType, readonly: boolean): Type | undefined {
|
||||
if (type.types.length === 2) {
|
||||
const firstType = type.types[0];
|
||||
const secondType = type.types[1];
|
||||
if (every(type.types, isEmptyObjectTypeOrSpreadsIntoEmptyObject)) {
|
||||
return isEmptyObjectType(firstType) ? firstType : isEmptyObjectType(secondType) ? secondType : emptyObjectType;
|
||||
}
|
||||
if (isEmptyObjectTypeOrSpreadsIntoEmptyObject(firstType)) {
|
||||
return getAnonymousPartialType(secondType);
|
||||
}
|
||||
if (isEmptyObjectTypeOrSpreadsIntoEmptyObject(secondType)) {
|
||||
return getAnonymousPartialType(firstType);
|
||||
}
|
||||
if (every(type.types, isEmptyObjectTypeOrSpreadsIntoEmptyObject)) {
|
||||
return find(type.types, isEmptyObjectType) || emptyObjectType;
|
||||
}
|
||||
const firstType = find(type.types, t => !isEmptyObjectTypeOrSpreadsIntoEmptyObject(t));
|
||||
if (!firstType) {
|
||||
return undefined;
|
||||
}
|
||||
const secondType = firstType && find(type.types, t => t !== firstType && !isEmptyObjectTypeOrSpreadsIntoEmptyObject(t));
|
||||
if (secondType) {
|
||||
return undefined;
|
||||
}
|
||||
return getAnonymousPartialType(firstType);
|
||||
|
||||
function getAnonymousPartialType(type: Type) {
|
||||
// gets the type as if it had been spread, but where everything in the spread is made optional
|
||||
|
@ -14695,7 +14694,7 @@ namespace ts {
|
|||
const isSetonlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor);
|
||||
const flags = SymbolFlags.Property | SymbolFlags.Optional;
|
||||
const result = createSymbol(flags, prop.escapedName, getIsLateCheckFlag(prop) | (readonly ? CheckFlags.Readonly : 0));
|
||||
result.type = isSetonlyAccessor ? undefinedType : getTypeOfSymbol(prop);
|
||||
result.type = isSetonlyAccessor ? undefinedType : getUnionType([getTypeOfSymbol(prop), undefinedType]);
|
||||
result.declarations = prop.declarations;
|
||||
result.nameType = getSymbolLinks(prop).nameType;
|
||||
result.syntheticOrigin = prop;
|
||||
|
|
|
@ -229,8 +229,8 @@ function conditionalSpreadBoolean(b: boolean) : { x: number, y: number } {
|
|||
>14 : 14
|
||||
}
|
||||
let o2 = { ...b && { x: 21 }}
|
||||
>o2 : { x?: number; }
|
||||
>{ ...b && { x: 21 }} : { x?: number; }
|
||||
>o2 : { x?: number | undefined; }
|
||||
>{ ...b && { x: 21 }} : { x?: number | undefined; }
|
||||
>b && { x: 21 } : false | { x: number; }
|
||||
>b : boolean
|
||||
>{ x: 21 } : { x: number; }
|
||||
|
@ -270,8 +270,8 @@ function conditionalSpreadNumber(nt: number): { x: number, y: number } {
|
|||
>nt : number
|
||||
}
|
||||
let o2 = { ...nt && { x: nt }}
|
||||
>o2 : { x?: number; }
|
||||
>{ ...nt && { x: nt }} : { x?: number; }
|
||||
>o2 : { x?: number | undefined; }
|
||||
>{ ...nt && { x: nt }} : { x?: number | undefined; }
|
||||
>nt && { x: nt } : 0 | { x: number; }
|
||||
>nt : number
|
||||
>{ x: nt } : { x: number; }
|
||||
|
@ -311,8 +311,8 @@ function conditionalSpreadString(st: string): { x: string, y: number } {
|
|||
>st : string
|
||||
}
|
||||
let o2 = { ...st && { x: st }}
|
||||
>o2 : { x?: string; }
|
||||
>{ ...st && { x: st }} : { x?: string; }
|
||||
>o2 : { x?: string | undefined; }
|
||||
>{ ...st && { x: st }} : { x?: string | undefined; }
|
||||
>st && { x: st } : "" | { x: string; }
|
||||
>st : string
|
||||
>{ x: st } : { x: string; }
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
=== tests/cases/conformance/types/spread/objectSpreadRepeatedComplexity.ts ===
|
||||
function f(cnd: Record<number, boolean>){
|
||||
>f : (cnd: Record<number, boolean>) => { prop20a?: number; prop20b?: number; prop19a?: number; prop19b?: number; prop18a?: number; prop18b?: number; prop17a?: number; prop17b?: number; prop16a?: number; prop16b?: number; prop15a?: number; prop15b?: number; prop14a?: number; prop14b?: number; prop13a?: number; prop13b?: number; prop12a?: number; prop12b?: number; prop11a?: number; prop11b?: number; prop10a?: number; prop10b?: number; prop9a?: number; prop9b?: number; prop8a?: number; prop8b?: number; prop7a?: number; prop7b?: number; prop6a?: number; prop6b?: number; prop5a?: number; prop5b?: number; prop4a?: number; prop4b?: number; prop3a?: number; prop3b?: number; prop0?: number; }
|
||||
>f : (cnd: Record<number, boolean>) => { prop20a?: number | undefined; prop20b?: number | undefined; prop19a?: number | undefined; prop19b?: number | undefined; prop18a?: number | undefined; prop18b?: number | undefined; prop17a?: number | undefined; prop17b?: number | undefined; prop16a?: number | undefined; prop16b?: number | undefined; prop15a?: number | undefined; prop15b?: number | undefined; prop14a?: number | undefined; prop14b?: number | undefined; prop13a?: number | undefined; prop13b?: number | undefined; prop12a?: number | undefined; prop12b?: number | undefined; prop11a?: number | undefined; prop11b?: number | undefined; prop10a?: number | undefined; prop10b?: number | undefined; prop9a?: number | undefined; prop9b?: number | undefined; prop8a?: number | undefined; prop8b?: number | undefined; prop7a?: number | undefined; prop7b?: number | undefined; prop6a?: number | undefined; prop6b?: number | undefined; prop5a?: number | undefined; prop5b?: number | undefined; prop4a?: number | undefined; prop4b?: number | undefined; prop3a?: number | undefined; prop3b?: number | undefined; prop0?: number | undefined; }
|
||||
>cnd : Record<number, boolean>
|
||||
|
||||
// Type is a union of 2^(n-1) members, where n is the number of spread objects
|
||||
return {
|
||||
>{ // Without this one, it collapses to {} ? ...(cnd[1] && cnd[2] && { prop0: 0, }), // With one prop each, it collapses to a single object (#34853?) ...(cnd[3] && { prop3a: 1, prop3b: 1, }), ...(cnd[4] && { prop4a: 1, prop4b: 1, }), ...(cnd[5] && { prop5a: 1, prop5b: 1, }), ...(cnd[6] && { prop6a: 1, prop6b: 1, }), ...(cnd[7] && { prop7a: 1, prop7b: 1, }), ...(cnd[8] && { prop8a: 1, prop8b: 1, }), ...(cnd[9] && { prop9a: 1, prop9b: 1, }), ...(cnd[10] && { prop10a: 1, prop10b: 1, }), ...(cnd[11] && { prop11a: 1, prop11b: 1, }), ...(cnd[12] && { prop12a: 1, prop12b: 1, }), ...(cnd[13] && { prop13a: 1, prop13b: 1, }), ...(cnd[14] && { prop14a: 1, prop14b: 1, }), ...(cnd[15] && { prop15a: 1, prop15b: 1, }), ...(cnd[16] && { prop16a: 1, prop16b: 1, }), ...(cnd[17] && { prop17a: 1, prop17b: 1, }), ...(cnd[18] && { prop18a: 1, prop18b: 1, }), ...(cnd[19] && { prop19a: 1, prop19b: 1, }), ...(cnd[20] && { prop20a: 1, prop20b: 1, }), } : { prop20a?: number; prop20b?: number; prop19a?: number; prop19b?: number; prop18a?: number; prop18b?: number; prop17a?: number; prop17b?: number; prop16a?: number; prop16b?: number; prop15a?: number; prop15b?: number; prop14a?: number; prop14b?: number; prop13a?: number; prop13b?: number; prop12a?: number; prop12b?: number; prop11a?: number; prop11b?: number; prop10a?: number; prop10b?: number; prop9a?: number; prop9b?: number; prop8a?: number; prop8b?: number; prop7a?: number; prop7b?: number; prop6a?: number; prop6b?: number; prop5a?: number; prop5b?: number; prop4a?: number; prop4b?: number; prop3a?: number; prop3b?: number; prop0?: number; }
|
||||
>{ // Without this one, it collapses to {} ? ...(cnd[1] && cnd[2] && { prop0: 0, }), // With one prop each, it collapses to a single object (#34853?) ...(cnd[3] && { prop3a: 1, prop3b: 1, }), ...(cnd[4] && { prop4a: 1, prop4b: 1, }), ...(cnd[5] && { prop5a: 1, prop5b: 1, }), ...(cnd[6] && { prop6a: 1, prop6b: 1, }), ...(cnd[7] && { prop7a: 1, prop7b: 1, }), ...(cnd[8] && { prop8a: 1, prop8b: 1, }), ...(cnd[9] && { prop9a: 1, prop9b: 1, }), ...(cnd[10] && { prop10a: 1, prop10b: 1, }), ...(cnd[11] && { prop11a: 1, prop11b: 1, }), ...(cnd[12] && { prop12a: 1, prop12b: 1, }), ...(cnd[13] && { prop13a: 1, prop13b: 1, }), ...(cnd[14] && { prop14a: 1, prop14b: 1, }), ...(cnd[15] && { prop15a: 1, prop15b: 1, }), ...(cnd[16] && { prop16a: 1, prop16b: 1, }), ...(cnd[17] && { prop17a: 1, prop17b: 1, }), ...(cnd[18] && { prop18a: 1, prop18b: 1, }), ...(cnd[19] && { prop19a: 1, prop19b: 1, }), ...(cnd[20] && { prop20a: 1, prop20b: 1, }), } : { prop20a?: number | undefined; prop20b?: number | undefined; prop19a?: number | undefined; prop19b?: number | undefined; prop18a?: number | undefined; prop18b?: number | undefined; prop17a?: number | undefined; prop17b?: number | undefined; prop16a?: number | undefined; prop16b?: number | undefined; prop15a?: number | undefined; prop15b?: number | undefined; prop14a?: number | undefined; prop14b?: number | undefined; prop13a?: number | undefined; prop13b?: number | undefined; prop12a?: number | undefined; prop12b?: number | undefined; prop11a?: number | undefined; prop11b?: number | undefined; prop10a?: number | undefined; prop10b?: number | undefined; prop9a?: number | undefined; prop9b?: number | undefined; prop8a?: number | undefined; prop8b?: number | undefined; prop7a?: number | undefined; prop7b?: number | undefined; prop6a?: number | undefined; prop6b?: number | undefined; prop5a?: number | undefined; prop5b?: number | undefined; prop4a?: number | undefined; prop4b?: number | undefined; prop3a?: number | undefined; prop3b?: number | undefined; prop0?: number | undefined; }
|
||||
|
||||
// Without this one, it collapses to {} ?
|
||||
...(cnd[1] &&
|
||||
|
|
|
@ -84,7 +84,7 @@ function parseWithSpread(config: Record<string, number>): Props {
|
|||
>config : Record<string, number>
|
||||
|
||||
return {
|
||||
>{ ...config.a !== undefined && { a: config.a.toString() }, ...config.b !== undefined && { b: config.b.toString() }, ...config.c !== undefined && { c: config.c.toString() }, ...config.d !== undefined && { d: config.d.toString() }, ...config.e !== undefined && { e: config.e.toString() }, ...config.f !== undefined && { f: config.f.toString() }, ...config.g !== undefined && { g: config.g.toString() }, ...config.h !== undefined && { h: config.h.toString() }, ...config.i !== undefined && { i: config.i.toString() }, ...config.j !== undefined && { j: config.j.toString() }, ...config.k !== undefined && { k: config.k.toString() }, ...config.l !== undefined && { l: config.l.toString() }, ...config.m !== undefined && { m: config.m.toString() }, ...config.n !== undefined && { n: config.n.toString() }, ...config.o !== undefined && { o: config.o.toString() }, ...config.p !== undefined && { p: config.p.toString() }, ...config.q !== undefined && { q: config.q.toString() }, ...config.r !== undefined && { r: config.r.toString() }, ...config.s !== undefined && { s: config.s.toString() }, ...config.t !== undefined && { t: config.t.toString() }, ...config.u !== undefined && { u: config.u.toString() }, ...config.v !== undefined && { v: config.v.toString() }, ...config.w !== undefined && { w: config.w.toString() }, ...config.x !== undefined && { x: config.x.toString() }, ...config.y !== undefined && { y: config.y.toString() }, ...config.z !== undefined && { z: config.z.toString() } } : { z?: string; y?: string; x?: string; w?: string; v?: string; u?: string; t?: string; s?: string; r?: string; q?: string; p?: string; o?: string; n?: string; m?: string; l?: string; k?: string; j?: string; i?: string; h?: string; g?: string; f?: string; e?: string; d?: string; c?: string; b?: string; a?: string; }
|
||||
>{ ...config.a !== undefined && { a: config.a.toString() }, ...config.b !== undefined && { b: config.b.toString() }, ...config.c !== undefined && { c: config.c.toString() }, ...config.d !== undefined && { d: config.d.toString() }, ...config.e !== undefined && { e: config.e.toString() }, ...config.f !== undefined && { f: config.f.toString() }, ...config.g !== undefined && { g: config.g.toString() }, ...config.h !== undefined && { h: config.h.toString() }, ...config.i !== undefined && { i: config.i.toString() }, ...config.j !== undefined && { j: config.j.toString() }, ...config.k !== undefined && { k: config.k.toString() }, ...config.l !== undefined && { l: config.l.toString() }, ...config.m !== undefined && { m: config.m.toString() }, ...config.n !== undefined && { n: config.n.toString() }, ...config.o !== undefined && { o: config.o.toString() }, ...config.p !== undefined && { p: config.p.toString() }, ...config.q !== undefined && { q: config.q.toString() }, ...config.r !== undefined && { r: config.r.toString() }, ...config.s !== undefined && { s: config.s.toString() }, ...config.t !== undefined && { t: config.t.toString() }, ...config.u !== undefined && { u: config.u.toString() }, ...config.v !== undefined && { v: config.v.toString() }, ...config.w !== undefined && { w: config.w.toString() }, ...config.x !== undefined && { x: config.x.toString() }, ...config.y !== undefined && { y: config.y.toString() }, ...config.z !== undefined && { z: config.z.toString() } } : { z?: string | undefined; y?: string | undefined; x?: string | undefined; w?: string | undefined; v?: string | undefined; u?: string | undefined; t?: string | undefined; s?: string | undefined; r?: string | undefined; q?: string | undefined; p?: string | undefined; o?: string | undefined; n?: string | undefined; m?: string | undefined; l?: string | undefined; k?: string | undefined; j?: string | undefined; i?: string | undefined; h?: string | undefined; g?: string | undefined; f?: string | undefined; e?: string | undefined; d?: string | undefined; c?: string | undefined; b?: string | undefined; a?: string | undefined; }
|
||||
|
||||
...config.a !== undefined && { a: config.a.toString() },
|
||||
>config.a !== undefined && { a: config.a.toString() } : false | { a: string; }
|
||||
|
|
48
tests/baselines/reference/spreadIdenticalTypesRemoved.js
Normal file
48
tests/baselines/reference/spreadIdenticalTypesRemoved.js
Normal file
|
@ -0,0 +1,48 @@
|
|||
//// [spreadIdenticalTypesRemoved.ts]
|
||||
interface Animal {
|
||||
name: string;
|
||||
kind: string;
|
||||
age: number;
|
||||
location: string;
|
||||
owner: object;
|
||||
}
|
||||
|
||||
function clonePet(pet: Animal, fullCopy?: boolean) {
|
||||
return {
|
||||
name: pet.name,
|
||||
kind: pet.kind,
|
||||
...(fullCopy && pet),
|
||||
}
|
||||
}
|
||||
|
||||
interface Animal2 {
|
||||
name: string;
|
||||
owner?: string;
|
||||
}
|
||||
function billOwner(pet: Animal2) {
|
||||
return {
|
||||
...(pet.owner && pet),
|
||||
paid: false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [spreadIdenticalTypesRemoved.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);
|
||||
};
|
||||
function clonePet(pet, fullCopy) {
|
||||
return __assign({ name: pet.name, kind: pet.kind }, (fullCopy && pet));
|
||||
}
|
||||
function billOwner(pet) {
|
||||
return __assign(__assign({}, (pet.owner && pet)), { paid: false });
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
=== tests/cases/compiler/spreadIdenticalTypesRemoved.ts ===
|
||||
interface Animal {
|
||||
>Animal : Symbol(Animal, Decl(spreadIdenticalTypesRemoved.ts, 0, 0))
|
||||
|
||||
name: string;
|
||||
>name : Symbol(Animal.name, Decl(spreadIdenticalTypesRemoved.ts, 0, 18))
|
||||
|
||||
kind: string;
|
||||
>kind : Symbol(Animal.kind, Decl(spreadIdenticalTypesRemoved.ts, 1, 17))
|
||||
|
||||
age: number;
|
||||
>age : Symbol(Animal.age, Decl(spreadIdenticalTypesRemoved.ts, 2, 17))
|
||||
|
||||
location: string;
|
||||
>location : Symbol(Animal.location, Decl(spreadIdenticalTypesRemoved.ts, 3, 16))
|
||||
|
||||
owner: object;
|
||||
>owner : Symbol(Animal.owner, Decl(spreadIdenticalTypesRemoved.ts, 4, 21))
|
||||
}
|
||||
|
||||
function clonePet(pet: Animal, fullCopy?: boolean) {
|
||||
>clonePet : Symbol(clonePet, Decl(spreadIdenticalTypesRemoved.ts, 6, 1))
|
||||
>pet : Symbol(pet, Decl(spreadIdenticalTypesRemoved.ts, 8, 18))
|
||||
>Animal : Symbol(Animal, Decl(spreadIdenticalTypesRemoved.ts, 0, 0))
|
||||
>fullCopy : Symbol(fullCopy, Decl(spreadIdenticalTypesRemoved.ts, 8, 30))
|
||||
|
||||
return {
|
||||
name: pet.name,
|
||||
>name : Symbol(name, Decl(spreadIdenticalTypesRemoved.ts, 9, 12))
|
||||
>pet.name : Symbol(Animal.name, Decl(spreadIdenticalTypesRemoved.ts, 0, 18))
|
||||
>pet : Symbol(pet, Decl(spreadIdenticalTypesRemoved.ts, 8, 18))
|
||||
>name : Symbol(Animal.name, Decl(spreadIdenticalTypesRemoved.ts, 0, 18))
|
||||
|
||||
kind: pet.kind,
|
||||
>kind : Symbol(kind, Decl(spreadIdenticalTypesRemoved.ts, 10, 23))
|
||||
>pet.kind : Symbol(Animal.kind, Decl(spreadIdenticalTypesRemoved.ts, 1, 17))
|
||||
>pet : Symbol(pet, Decl(spreadIdenticalTypesRemoved.ts, 8, 18))
|
||||
>kind : Symbol(Animal.kind, Decl(spreadIdenticalTypesRemoved.ts, 1, 17))
|
||||
|
||||
...(fullCopy && pet),
|
||||
>fullCopy : Symbol(fullCopy, Decl(spreadIdenticalTypesRemoved.ts, 8, 30))
|
||||
>pet : Symbol(pet, Decl(spreadIdenticalTypesRemoved.ts, 8, 18))
|
||||
}
|
||||
}
|
||||
|
||||
interface Animal2 {
|
||||
>Animal2 : Symbol(Animal2, Decl(spreadIdenticalTypesRemoved.ts, 14, 1))
|
||||
|
||||
name: string;
|
||||
>name : Symbol(Animal2.name, Decl(spreadIdenticalTypesRemoved.ts, 16, 19))
|
||||
|
||||
owner?: string;
|
||||
>owner : Symbol(Animal2.owner, Decl(spreadIdenticalTypesRemoved.ts, 17, 17))
|
||||
}
|
||||
function billOwner(pet: Animal2) {
|
||||
>billOwner : Symbol(billOwner, Decl(spreadIdenticalTypesRemoved.ts, 19, 1))
|
||||
>pet : Symbol(pet, Decl(spreadIdenticalTypesRemoved.ts, 20, 19))
|
||||
>Animal2 : Symbol(Animal2, Decl(spreadIdenticalTypesRemoved.ts, 14, 1))
|
||||
|
||||
return {
|
||||
...(pet.owner && pet),
|
||||
>pet.owner : Symbol(Animal2.owner, Decl(spreadIdenticalTypesRemoved.ts, 17, 17))
|
||||
>pet : Symbol(pet, Decl(spreadIdenticalTypesRemoved.ts, 20, 19))
|
||||
>owner : Symbol(Animal2.owner, Decl(spreadIdenticalTypesRemoved.ts, 17, 17))
|
||||
>pet : Symbol(pet, Decl(spreadIdenticalTypesRemoved.ts, 20, 19))
|
||||
|
||||
paid: false
|
||||
>paid : Symbol(paid, Decl(spreadIdenticalTypesRemoved.ts, 22, 30))
|
||||
}
|
||||
}
|
||||
|
74
tests/baselines/reference/spreadIdenticalTypesRemoved.types
Normal file
74
tests/baselines/reference/spreadIdenticalTypesRemoved.types
Normal file
|
@ -0,0 +1,74 @@
|
|||
=== tests/cases/compiler/spreadIdenticalTypesRemoved.ts ===
|
||||
interface Animal {
|
||||
name: string;
|
||||
>name : string
|
||||
|
||||
kind: string;
|
||||
>kind : string
|
||||
|
||||
age: number;
|
||||
>age : number
|
||||
|
||||
location: string;
|
||||
>location : string
|
||||
|
||||
owner: object;
|
||||
>owner : object
|
||||
}
|
||||
|
||||
function clonePet(pet: Animal, fullCopy?: boolean) {
|
||||
>clonePet : (pet: Animal, fullCopy?: boolean | undefined) => { name: string; kind: string; age?: number | undefined; location?: string | undefined; owner?: object | undefined; }
|
||||
>pet : Animal
|
||||
>fullCopy : boolean | undefined
|
||||
|
||||
return {
|
||||
>{ name: pet.name, kind: pet.kind, ...(fullCopy && pet), } : { name: string; kind: string; age?: number | undefined; location?: string | undefined; owner?: object | undefined; }
|
||||
|
||||
name: pet.name,
|
||||
>name : string
|
||||
>pet.name : string
|
||||
>pet : Animal
|
||||
>name : string
|
||||
|
||||
kind: pet.kind,
|
||||
>kind : string
|
||||
>pet.kind : string
|
||||
>pet : Animal
|
||||
>kind : string
|
||||
|
||||
...(fullCopy && pet),
|
||||
>(fullCopy && pet) : false | Animal | undefined
|
||||
>fullCopy && pet : false | Animal | undefined
|
||||
>fullCopy : boolean | undefined
|
||||
>pet : Animal
|
||||
}
|
||||
}
|
||||
|
||||
interface Animal2 {
|
||||
name: string;
|
||||
>name : string
|
||||
|
||||
owner?: string;
|
||||
>owner : string | undefined
|
||||
}
|
||||
function billOwner(pet: Animal2) {
|
||||
>billOwner : (pet: Animal2) => { paid: boolean; name?: string | undefined; owner?: string | undefined; }
|
||||
>pet : Animal2
|
||||
|
||||
return {
|
||||
>{ ...(pet.owner && pet), paid: false } : { paid: boolean; name?: string | undefined; owner?: string | undefined; }
|
||||
|
||||
...(pet.owner && pet),
|
||||
>(pet.owner && pet) : "" | Animal2 | undefined
|
||||
>pet.owner && pet : "" | Animal2 | undefined
|
||||
>pet.owner : string | undefined
|
||||
>pet : Animal2
|
||||
>owner : string | undefined
|
||||
>pet : Animal2
|
||||
|
||||
paid: false
|
||||
>paid : boolean
|
||||
>false : false
|
||||
}
|
||||
}
|
||||
|
|
@ -9,11 +9,11 @@ const recordOfRecords: RecordOfRecords = {}
|
|||
>{} : {}
|
||||
|
||||
recordOfRecords.propA = {...(foo !== undefined ? {foo} : {})} // OK
|
||||
>recordOfRecords.propA = {...(foo !== undefined ? {foo} : {})} : { foo?: Record<never, never>; }
|
||||
>recordOfRecords.propA = {...(foo !== undefined ? {foo} : {})} : { foo?: Record<never, never> | undefined; }
|
||||
>recordOfRecords.propA : RecordOfRecords
|
||||
>recordOfRecords : RecordOfRecords
|
||||
>propA : RecordOfRecords
|
||||
>{...(foo !== undefined ? {foo} : {})} : { foo?: Record<never, never>; }
|
||||
>{...(foo !== undefined ? {foo} : {})} : { foo?: Record<never, never> | undefined; }
|
||||
>(foo !== undefined ? {foo} : {}) : { foo: Record<never, never>; } | {}
|
||||
>foo !== undefined ? {foo} : {} : { foo: Record<never, never>; } | {}
|
||||
>foo !== undefined : boolean
|
||||
|
@ -36,11 +36,11 @@ recordOfRecords.propB = {...(foo && {foo})} // OK
|
|||
>foo : Record<never, never>
|
||||
|
||||
recordOfRecords.propC = {...(foo !== undefined && {foo})} // error'd in 3.7 beta, should be OK
|
||||
>recordOfRecords.propC = {...(foo !== undefined && {foo})} : { foo?: Record<never, never>; }
|
||||
>recordOfRecords.propC = {...(foo !== undefined && {foo})} : { foo?: Record<never, never> | undefined; }
|
||||
>recordOfRecords.propC : RecordOfRecords
|
||||
>recordOfRecords : RecordOfRecords
|
||||
>propC : RecordOfRecords
|
||||
>{...(foo !== undefined && {foo})} : { foo?: Record<never, never>; }
|
||||
>{...(foo !== undefined && {foo})} : { foo?: Record<never, never> | undefined; }
|
||||
>(foo !== undefined && {foo}) : false | { foo: Record<never, never>; }
|
||||
>foo !== undefined && {foo} : false | { foo: Record<never, never>; }
|
||||
>foo !== undefined : boolean
|
||||
|
@ -55,11 +55,11 @@ const recordsOfRecordsOrEmpty: RecordOfRecordsOrEmpty = {}
|
|||
>{} : {}
|
||||
|
||||
recordsOfRecordsOrEmpty.propA = {...(foo !== undefined ? {foo} : {})} // OK
|
||||
>recordsOfRecordsOrEmpty.propA = {...(foo !== undefined ? {foo} : {})} : { foo?: Record<never, never>; }
|
||||
>recordsOfRecordsOrEmpty.propA = {...(foo !== undefined ? {foo} : {})} : { foo?: Record<never, never> | undefined; }
|
||||
>recordsOfRecordsOrEmpty.propA : {} | RecordOfRecordsOrEmpty
|
||||
>recordsOfRecordsOrEmpty : RecordOfRecordsOrEmpty
|
||||
>propA : {} | RecordOfRecordsOrEmpty
|
||||
>{...(foo !== undefined ? {foo} : {})} : { foo?: Record<never, never>; }
|
||||
>{...(foo !== undefined ? {foo} : {})} : { foo?: Record<never, never> | undefined; }
|
||||
>(foo !== undefined ? {foo} : {}) : { foo: Record<never, never>; } | {}
|
||||
>foo !== undefined ? {foo} : {} : { foo: Record<never, never>; } | {}
|
||||
>foo !== undefined : boolean
|
||||
|
@ -82,11 +82,11 @@ recordsOfRecordsOrEmpty.propB = {...(foo && {foo})} // OK
|
|||
>foo : Record<never, never>
|
||||
|
||||
recordsOfRecordsOrEmpty.propC = {...(foo !== undefined && {foo})} // OK
|
||||
>recordsOfRecordsOrEmpty.propC = {...(foo !== undefined && {foo})} : { foo?: Record<never, never>; }
|
||||
>recordsOfRecordsOrEmpty.propC = {...(foo !== undefined && {foo})} : { foo?: Record<never, never> | undefined; }
|
||||
>recordsOfRecordsOrEmpty.propC : {} | RecordOfRecordsOrEmpty
|
||||
>recordsOfRecordsOrEmpty : RecordOfRecordsOrEmpty
|
||||
>propC : {} | RecordOfRecordsOrEmpty
|
||||
>{...(foo !== undefined && {foo})} : { foo?: Record<never, never>; }
|
||||
>{...(foo !== undefined && {foo})} : { foo?: Record<never, never> | undefined; }
|
||||
>(foo !== undefined && {foo}) : false | { foo: Record<never, never>; }
|
||||
>foo !== undefined && {foo} : false | { foo: Record<never, never>; }
|
||||
>foo !== undefined : boolean
|
||||
|
|
|
@ -78,14 +78,14 @@ function h(obj: { x: number } | { x: string }) {
|
|||
>obj : { x: number; } | { x: string; }
|
||||
}
|
||||
function i(b: boolean, t: { command: string, ok: string }) {
|
||||
>i : (b: boolean, t: { command: string; ok: string;}) => { command: string; ok?: string; }
|
||||
>i : (b: boolean, t: { command: string; ok: string;}) => { command: string; ok?: string | undefined; }
|
||||
>b : boolean
|
||||
>t : { command: string; ok: string; }
|
||||
>command : string
|
||||
>ok : string
|
||||
|
||||
return { command: "hi", ...(b ? t : {}) } // ok
|
||||
>{ command: "hi", ...(b ? t : {}) } : { command: string; ok?: string; }
|
||||
>{ command: "hi", ...(b ? t : {}) } : { command: string; ok?: string | undefined; }
|
||||
>command : string
|
||||
>"hi" : "hi"
|
||||
>(b ? t : {}) : { command: string; ok: string; } | {}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
tests/cases/conformance/types/spread/spreadUnion2.ts(5,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o1' must be of type '{} | { a: number; }', but here has type '{ a?: number; }'.
|
||||
tests/cases/conformance/types/spread/spreadUnion2.ts(8,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o2' must be of type '{} | { b: number; }', but here has type '{ b?: number; }'.
|
||||
tests/cases/conformance/types/spread/spreadUnion2.ts(11,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o3' must be of type '{} | { a: number; } | { b: number; } | { a: number; b: number; }', but here has type '{ b?: number; a?: number; }'.
|
||||
tests/cases/conformance/types/spread/spreadUnion2.ts(12,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o3' must be of type '{} | { a: number; } | { b: number; } | { a: number; b: number; }', but here has type '{ a?: number; b?: number; }'.
|
||||
tests/cases/conformance/types/spread/spreadUnion2.ts(15,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o4' must be of type '{} | { a: number; }', but here has type '{ a?: number; }'.
|
||||
tests/cases/conformance/types/spread/spreadUnion2.ts(18,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o5' must be of type '{} | { b: number; }', but here has type '{ b?: number; }'.
|
||||
tests/cases/conformance/types/spread/spreadUnion2.ts(5,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o1' must be of type '{} | { a: number; }', but here has type '{ a?: number | undefined; }'.
|
||||
tests/cases/conformance/types/spread/spreadUnion2.ts(8,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o2' must be of type '{} | { b: number; }', but here has type '{ b?: number | undefined; }'.
|
||||
tests/cases/conformance/types/spread/spreadUnion2.ts(11,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o3' must be of type '{} | { a: number; } | { b: number; } | { a: number; b: number; }', but here has type '{ b?: number | undefined; a?: number | undefined; }'.
|
||||
tests/cases/conformance/types/spread/spreadUnion2.ts(12,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o3' must be of type '{} | { a: number; } | { b: number; } | { a: number; b: number; }', but here has type '{ a?: number | undefined; b?: number | undefined; }'.
|
||||
tests/cases/conformance/types/spread/spreadUnion2.ts(15,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o4' must be of type '{} | { a: number; }', but here has type '{ a?: number | undefined; }'.
|
||||
tests/cases/conformance/types/spread/spreadUnion2.ts(18,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'o5' must be of type '{} | { b: number; }', but here has type '{ b?: number | undefined; }'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/spread/spreadUnion2.ts (6 errors) ====
|
||||
|
@ -13,35 +13,35 @@ tests/cases/conformance/types/spread/spreadUnion2.ts(18,5): error TS2403: Subseq
|
|||
var o1: {} | { a: number };
|
||||
var o1 = { ...undefinedUnion };
|
||||
~~
|
||||
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o1' must be of type '{} | { a: number; }', but here has type '{ a?: number; }'.
|
||||
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o1' must be of type '{} | { a: number; }', but here has type '{ a?: number | undefined; }'.
|
||||
!!! related TS6203 tests/cases/conformance/types/spread/spreadUnion2.ts:4:5: 'o1' was also declared here.
|
||||
|
||||
var o2: {} | { b: number };
|
||||
var o2 = { ...nullUnion };
|
||||
~~
|
||||
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o2' must be of type '{} | { b: number; }', but here has type '{ b?: number; }'.
|
||||
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o2' must be of type '{} | { b: number; }', but here has type '{ b?: number | undefined; }'.
|
||||
!!! related TS6203 tests/cases/conformance/types/spread/spreadUnion2.ts:7:5: 'o2' was also declared here.
|
||||
|
||||
var o3: {} | { a: number } | { b: number } | { a: number, b: number };
|
||||
var o3 = { ...undefinedUnion, ...nullUnion };
|
||||
~~
|
||||
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o3' must be of type '{} | { a: number; } | { b: number; } | { a: number; b: number; }', but here has type '{ b?: number; a?: number; }'.
|
||||
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o3' must be of type '{} | { a: number; } | { b: number; } | { a: number; b: number; }', but here has type '{ b?: number | undefined; a?: number | undefined; }'.
|
||||
!!! related TS6203 tests/cases/conformance/types/spread/spreadUnion2.ts:10:5: 'o3' was also declared here.
|
||||
var o3 = { ...nullUnion, ...undefinedUnion };
|
||||
~~
|
||||
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o3' must be of type '{} | { a: number; } | { b: number; } | { a: number; b: number; }', but here has type '{ a?: number; b?: number; }'.
|
||||
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o3' must be of type '{} | { a: number; } | { b: number; } | { a: number; b: number; }', but here has type '{ a?: number | undefined; b?: number | undefined; }'.
|
||||
!!! related TS6203 tests/cases/conformance/types/spread/spreadUnion2.ts:10:5: 'o3' was also declared here.
|
||||
|
||||
var o4: {} | { a: number };
|
||||
var o4 = { ...undefinedUnion, ...undefinedUnion };
|
||||
~~
|
||||
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o4' must be of type '{} | { a: number; }', but here has type '{ a?: number; }'.
|
||||
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o4' must be of type '{} | { a: number; }', but here has type '{ a?: number | undefined; }'.
|
||||
!!! related TS6203 tests/cases/conformance/types/spread/spreadUnion2.ts:14:5: 'o4' was also declared here.
|
||||
|
||||
var o5: {} | { b: number };
|
||||
var o5 = { ...nullUnion, ...nullUnion };
|
||||
~~
|
||||
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o5' must be of type '{} | { b: number; }', but here has type '{ b?: number; }'.
|
||||
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'o5' must be of type '{} | { b: number; }', but here has type '{ b?: number | undefined; }'.
|
||||
!!! related TS6203 tests/cases/conformance/types/spread/spreadUnion2.ts:17:5: 'o5' was also declared here.
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ var o1: {} | { a: number };
|
|||
|
||||
var o1 = { ...undefinedUnion };
|
||||
>o1 : {} | { a: number; }
|
||||
>{ ...undefinedUnion } : { a?: number; }
|
||||
>{ ...undefinedUnion } : { a?: number | undefined; }
|
||||
>undefinedUnion : { a: number; } | undefined
|
||||
|
||||
var o2: {} | { b: number };
|
||||
|
@ -23,7 +23,7 @@ var o2: {} | { b: number };
|
|||
|
||||
var o2 = { ...nullUnion };
|
||||
>o2 : {} | { b: number; }
|
||||
>{ ...nullUnion } : { b?: number; }
|
||||
>{ ...nullUnion } : { b?: number | undefined; }
|
||||
>nullUnion : { b: number; } | null
|
||||
|
||||
var o3: {} | { a: number } | { b: number } | { a: number, b: number };
|
||||
|
@ -35,13 +35,13 @@ var o3: {} | { a: number } | { b: number } | { a: number, b: number };
|
|||
|
||||
var o3 = { ...undefinedUnion, ...nullUnion };
|
||||
>o3 : {} | { a: number; } | { b: number; } | { a: number; b: number; }
|
||||
>{ ...undefinedUnion, ...nullUnion } : { b?: number; a?: number; }
|
||||
>{ ...undefinedUnion, ...nullUnion } : { b?: number | undefined; a?: number | undefined; }
|
||||
>undefinedUnion : { a: number; } | undefined
|
||||
>nullUnion : { b: number; } | null
|
||||
|
||||
var o3 = { ...nullUnion, ...undefinedUnion };
|
||||
>o3 : {} | { a: number; } | { b: number; } | { a: number; b: number; }
|
||||
>{ ...nullUnion, ...undefinedUnion } : { a?: number; b?: number; }
|
||||
>{ ...nullUnion, ...undefinedUnion } : { a?: number | undefined; b?: number | undefined; }
|
||||
>nullUnion : { b: number; } | null
|
||||
>undefinedUnion : { a: number; } | undefined
|
||||
|
||||
|
@ -51,7 +51,7 @@ var o4: {} | { a: number };
|
|||
|
||||
var o4 = { ...undefinedUnion, ...undefinedUnion };
|
||||
>o4 : {} | { a: number; }
|
||||
>{ ...undefinedUnion, ...undefinedUnion } : { a?: number; }
|
||||
>{ ...undefinedUnion, ...undefinedUnion } : { a?: number | undefined; }
|
||||
>undefinedUnion : { a: number; } | undefined
|
||||
>undefinedUnion : { a: number; } | undefined
|
||||
|
||||
|
@ -61,7 +61,7 @@ var o5: {} | { b: number };
|
|||
|
||||
var o5 = { ...nullUnion, ...nullUnion };
|
||||
>o5 : {} | { b: number; }
|
||||
>{ ...nullUnion, ...nullUnion } : { b?: number; }
|
||||
>{ ...nullUnion, ...nullUnion } : { b?: number | undefined; }
|
||||
>nullUnion : { b: number; } | null
|
||||
>nullUnion : { b: number; } | null
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
tests/cases/conformance/types/spread/spreadUnion3.ts(2,14): error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/types/spread/spreadUnion3.ts(9,23): error TS2339: Property 'a' does not exist on type '{}'.
|
||||
tests/cases/conformance/types/spread/spreadUnion3.ts(9,9): error TS2322: Type 'number | undefined' is not assignable to type 'number'.
|
||||
Type 'undefined' is not assignable to type 'number'.
|
||||
tests/cases/conformance/types/spread/spreadUnion3.ts(17,11): error TS2698: Spread types may only be created from object types.
|
||||
tests/cases/conformance/types/spread/spreadUnion3.ts(18,11): error TS2698: Spread types may only be created from object types.
|
||||
|
||||
|
@ -17,8 +18,9 @@ tests/cases/conformance/types/spread/spreadUnion3.ts(18,11): error TS2698: Sprea
|
|||
function g(t?: { a: number } | null): void {
|
||||
let b = { ...t };
|
||||
let c: number = b.a; // might not have 'a'
|
||||
~
|
||||
!!! error TS2339: Property 'a' does not exist on type '{}'.
|
||||
~
|
||||
!!! error TS2322: Type 'number | undefined' is not assignable to type 'number'.
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'number'.
|
||||
}
|
||||
g()
|
||||
g(undefined)
|
||||
|
|
|
@ -25,7 +25,9 @@ function g(t?: { a: number } | null): void {
|
|||
|
||||
let c: number = b.a; // might not have 'a'
|
||||
>c : Symbol(c, Decl(spreadUnion3.ts, 8, 7))
|
||||
>b.a : Symbol(a, Decl(spreadUnion3.ts, 6, 16))
|
||||
>b : Symbol(b, Decl(spreadUnion3.ts, 7, 7))
|
||||
>a : Symbol(a, Decl(spreadUnion3.ts, 6, 16))
|
||||
}
|
||||
g()
|
||||
>g : Symbol(g, Decl(spreadUnion3.ts, 3, 12))
|
||||
|
|
|
@ -24,15 +24,15 @@ function g(t?: { a: number } | null): void {
|
|||
>null : null
|
||||
|
||||
let b = { ...t };
|
||||
>b : {}
|
||||
>{ ...t } : {} | {} | { a: number; }
|
||||
>b : { a?: number | undefined; }
|
||||
>{ ...t } : { a?: number | undefined; }
|
||||
>t : { a: number; } | null | undefined
|
||||
|
||||
let c: number = b.a; // might not have 'a'
|
||||
>c : number
|
||||
>b.a : any
|
||||
>b : {}
|
||||
>a : any
|
||||
>b.a : number | undefined
|
||||
>b : { a?: number | undefined; }
|
||||
>a : number | undefined
|
||||
}
|
||||
g()
|
||||
>g() : void
|
||||
|
|
27
tests/cases/compiler/spreadIdenticalTypesRemoved.ts
Normal file
27
tests/cases/compiler/spreadIdenticalTypesRemoved.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
// @strict: true
|
||||
interface Animal {
|
||||
name: string;
|
||||
kind: string;
|
||||
age: number;
|
||||
location: string;
|
||||
owner: object;
|
||||
}
|
||||
|
||||
function clonePet(pet: Animal, fullCopy?: boolean) {
|
||||
return {
|
||||
name: pet.name,
|
||||
kind: pet.kind,
|
||||
...(fullCopy && pet),
|
||||
}
|
||||
}
|
||||
|
||||
interface Animal2 {
|
||||
name: string;
|
||||
owner?: string;
|
||||
}
|
||||
function billOwner(pet: Animal2) {
|
||||
return {
|
||||
...(pet.owner && pet),
|
||||
paid: false
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue