Map stale empty object type in union into fresh empty object type after spread is complete (#34839)
* Map stale empty object type in union into fresh empty object type after spread is complete * Accept minor baseline diff
This commit is contained in:
parent
0d993ac592
commit
a6d44aa52e
|
@ -22090,8 +22090,13 @@ namespace ts {
|
|||
if (spread !== emptyObjectType) {
|
||||
if (propertiesArray.length > 0) {
|
||||
spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, objectFlags, inConstContext);
|
||||
propertiesArray = [];
|
||||
propertiesTable = createSymbolTable();
|
||||
hasComputedStringProperty = false;
|
||||
hasComputedNumberProperty = false;
|
||||
}
|
||||
return spread;
|
||||
// remap the raw emptyObjectType fed in at the top into a fresh empty object literal type, unique to this use site
|
||||
return mapType(spread, t => t === emptyObjectType ? createObjectLiteralType() : t);
|
||||
}
|
||||
|
||||
return createObjectLiteralType();
|
||||
|
|
|
@ -293,7 +293,7 @@ function conditionalSpreadBoolean(b: boolean) : { x: number, y: number } {
|
|||
}
|
||||
let o2 = { ...b && { x: 21 }}
|
||||
>o2 : {}
|
||||
>{ ...b && { x: 21 }} : {} | { x: number; }
|
||||
>{ ...b && { x: 21 }} : { x: number; } | {}
|
||||
>b && { x: 21 } : false | { x: number; }
|
||||
>b : boolean
|
||||
>{ x: 21 } : { x: number; }
|
||||
|
@ -334,7 +334,7 @@ function conditionalSpreadNumber(nt: number): { x: number, y: number } {
|
|||
}
|
||||
let o2 = { ...nt && { x: nt }}
|
||||
>o2 : {}
|
||||
>{ ...nt && { x: nt }} : {} | { x: number; }
|
||||
>{ ...nt && { x: nt }} : { x: number; } | {}
|
||||
>nt && { x: nt } : 0 | { x: number; }
|
||||
>nt : number
|
||||
>{ x: nt } : { x: number; }
|
||||
|
@ -375,7 +375,7 @@ function conditionalSpreadString(st: string): { x: string, y: number } {
|
|||
}
|
||||
let o2 = { ...st && { x: st }}
|
||||
>o2 : {}
|
||||
>{ ...st && { x: st }} : {} | { x: string; }
|
||||
>{ ...st && { x: st }} : { x: string; } | {}
|
||||
>st && { x: st } : "" | { x: string; }
|
||||
>st : string
|
||||
>{ x: st } : { x: string; }
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
//// [spreadOfObjectLiteralAssignableToIndexSignature.ts]
|
||||
const foo: Record<never, never> = {} // OK
|
||||
|
||||
interface RecordOfRecords extends Record<keyof any, RecordOfRecords> {}
|
||||
const recordOfRecords: RecordOfRecords = {}
|
||||
recordOfRecords.propA = {...(foo !== undefined ? {foo} : {})} // OK
|
||||
recordOfRecords.propB = {...(foo && {foo})} // OK
|
||||
recordOfRecords.propC = {...(foo !== undefined && {foo})} // error'd in 3.7 beta, should be OK
|
||||
|
||||
interface RecordOfRecordsOrEmpty extends Record<keyof any, RecordOfRecordsOrEmpty | {}> {}
|
||||
const recordsOfRecordsOrEmpty: RecordOfRecordsOrEmpty = {}
|
||||
recordsOfRecordsOrEmpty.propA = {...(foo !== undefined ? {foo} : {})} // OK
|
||||
recordsOfRecordsOrEmpty.propB = {...(foo && {foo})} // OK
|
||||
recordsOfRecordsOrEmpty.propC = {...(foo !== undefined && {foo})} // OK
|
||||
|
||||
//// [spreadOfObjectLiteralAssignableToIndexSignature.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 foo = {}; // OK
|
||||
var recordOfRecords = {};
|
||||
recordOfRecords.propA = __assign({}, (foo !== undefined ? { foo: foo } : {})); // OK
|
||||
recordOfRecords.propB = __assign({}, (foo && { foo: foo })); // OK
|
||||
recordOfRecords.propC = __assign({}, (foo !== undefined && { foo: foo })); // error'd in 3.7 beta, should be OK
|
||||
var recordsOfRecordsOrEmpty = {};
|
||||
recordsOfRecordsOrEmpty.propA = __assign({}, (foo !== undefined ? { foo: foo } : {})); // OK
|
||||
recordsOfRecordsOrEmpty.propB = __assign({}, (foo && { foo: foo })); // OK
|
||||
recordsOfRecordsOrEmpty.propC = __assign({}, (foo !== undefined && { foo: foo })); // OK
|
|
@ -0,0 +1,57 @@
|
|||
=== tests/cases/compiler/spreadOfObjectLiteralAssignableToIndexSignature.ts ===
|
||||
const foo: Record<never, never> = {} // OK
|
||||
>foo : Symbol(foo, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 0, 5))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
interface RecordOfRecords extends Record<keyof any, RecordOfRecords> {}
|
||||
>RecordOfRecords : Symbol(RecordOfRecords, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 0, 36))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>RecordOfRecords : Symbol(RecordOfRecords, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 0, 36))
|
||||
|
||||
const recordOfRecords: RecordOfRecords = {}
|
||||
>recordOfRecords : Symbol(recordOfRecords, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 3, 5))
|
||||
>RecordOfRecords : Symbol(RecordOfRecords, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 0, 36))
|
||||
|
||||
recordOfRecords.propA = {...(foo !== undefined ? {foo} : {})} // OK
|
||||
>recordOfRecords : Symbol(recordOfRecords, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 3, 5))
|
||||
>foo : Symbol(foo, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 0, 5))
|
||||
>undefined : Symbol(undefined)
|
||||
>foo : Symbol(foo, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 4, 50))
|
||||
|
||||
recordOfRecords.propB = {...(foo && {foo})} // OK
|
||||
>recordOfRecords : Symbol(recordOfRecords, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 3, 5))
|
||||
>foo : Symbol(foo, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 0, 5))
|
||||
>foo : Symbol(foo, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 5, 37))
|
||||
|
||||
recordOfRecords.propC = {...(foo !== undefined && {foo})} // error'd in 3.7 beta, should be OK
|
||||
>recordOfRecords : Symbol(recordOfRecords, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 3, 5))
|
||||
>foo : Symbol(foo, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 0, 5))
|
||||
>undefined : Symbol(undefined)
|
||||
>foo : Symbol(foo, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 6, 51))
|
||||
|
||||
interface RecordOfRecordsOrEmpty extends Record<keyof any, RecordOfRecordsOrEmpty | {}> {}
|
||||
>RecordOfRecordsOrEmpty : Symbol(RecordOfRecordsOrEmpty, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 6, 57))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>RecordOfRecordsOrEmpty : Symbol(RecordOfRecordsOrEmpty, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 6, 57))
|
||||
|
||||
const recordsOfRecordsOrEmpty: RecordOfRecordsOrEmpty = {}
|
||||
>recordsOfRecordsOrEmpty : Symbol(recordsOfRecordsOrEmpty, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 9, 5))
|
||||
>RecordOfRecordsOrEmpty : Symbol(RecordOfRecordsOrEmpty, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 6, 57))
|
||||
|
||||
recordsOfRecordsOrEmpty.propA = {...(foo !== undefined ? {foo} : {})} // OK
|
||||
>recordsOfRecordsOrEmpty : Symbol(recordsOfRecordsOrEmpty, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 9, 5))
|
||||
>foo : Symbol(foo, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 0, 5))
|
||||
>undefined : Symbol(undefined)
|
||||
>foo : Symbol(foo, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 10, 58))
|
||||
|
||||
recordsOfRecordsOrEmpty.propB = {...(foo && {foo})} // OK
|
||||
>recordsOfRecordsOrEmpty : Symbol(recordsOfRecordsOrEmpty, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 9, 5))
|
||||
>foo : Symbol(foo, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 0, 5))
|
||||
>foo : Symbol(foo, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 11, 45))
|
||||
|
||||
recordsOfRecordsOrEmpty.propC = {...(foo !== undefined && {foo})} // OK
|
||||
>recordsOfRecordsOrEmpty : Symbol(recordsOfRecordsOrEmpty, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 9, 5))
|
||||
>foo : Symbol(foo, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 0, 5))
|
||||
>undefined : Symbol(undefined)
|
||||
>foo : Symbol(foo, Decl(spreadOfObjectLiteralAssignableToIndexSignature.ts, 12, 59))
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
=== tests/cases/compiler/spreadOfObjectLiteralAssignableToIndexSignature.ts ===
|
||||
const foo: Record<never, never> = {} // OK
|
||||
>foo : Record<never, never>
|
||||
>{} : {}
|
||||
|
||||
interface RecordOfRecords extends Record<keyof any, RecordOfRecords> {}
|
||||
const recordOfRecords: RecordOfRecords = {}
|
||||
>recordOfRecords : RecordOfRecords
|
||||
>{} : {}
|
||||
|
||||
recordOfRecords.propA = {...(foo !== undefined ? {foo} : {})} // OK
|
||||
>recordOfRecords.propA = {...(foo !== undefined ? {foo} : {})} : { foo: Record<never, never>; } | {}
|
||||
>recordOfRecords.propA : RecordOfRecords
|
||||
>recordOfRecords : RecordOfRecords
|
||||
>propA : RecordOfRecords
|
||||
>{...(foo !== undefined ? {foo} : {})} : { foo: Record<never, never>; } | {}
|
||||
>(foo !== undefined ? {foo} : {}) : { foo: Record<never, never>; } | {}
|
||||
>foo !== undefined ? {foo} : {} : { foo: Record<never, never>; } | {}
|
||||
>foo !== undefined : boolean
|
||||
>foo : Record<never, never>
|
||||
>undefined : undefined
|
||||
>{foo} : { foo: Record<never, never>; }
|
||||
>foo : Record<never, never>
|
||||
>{} : {}
|
||||
|
||||
recordOfRecords.propB = {...(foo && {foo})} // OK
|
||||
>recordOfRecords.propB = {...(foo && {foo})} : { foo: Record<never, never>; }
|
||||
>recordOfRecords.propB : RecordOfRecords
|
||||
>recordOfRecords : RecordOfRecords
|
||||
>propB : RecordOfRecords
|
||||
>{...(foo && {foo})} : { foo: Record<never, never>; }
|
||||
>(foo && {foo}) : { foo: Record<never, never>; }
|
||||
>foo && {foo} : { foo: Record<never, never>; }
|
||||
>foo : Record<never, never>
|
||||
>{foo} : { foo: Record<never, never>; }
|
||||
>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 : RecordOfRecords
|
||||
>recordOfRecords : RecordOfRecords
|
||||
>propC : RecordOfRecords
|
||||
>{...(foo !== undefined && {foo})} : { foo: Record<never, never>; } | {}
|
||||
>(foo !== undefined && {foo}) : false | { foo: Record<never, never>; }
|
||||
>foo !== undefined && {foo} : false | { foo: Record<never, never>; }
|
||||
>foo !== undefined : boolean
|
||||
>foo : Record<never, never>
|
||||
>undefined : undefined
|
||||
>{foo} : { foo: Record<never, never>; }
|
||||
>foo : Record<never, never>
|
||||
|
||||
interface RecordOfRecordsOrEmpty extends Record<keyof any, RecordOfRecordsOrEmpty | {}> {}
|
||||
const recordsOfRecordsOrEmpty: RecordOfRecordsOrEmpty = {}
|
||||
>recordsOfRecordsOrEmpty : RecordOfRecordsOrEmpty
|
||||
>{} : {}
|
||||
|
||||
recordsOfRecordsOrEmpty.propA = {...(foo !== undefined ? {foo} : {})} // OK
|
||||
>recordsOfRecordsOrEmpty.propA = {...(foo !== undefined ? {foo} : {})} : { foo: Record<never, never>; } | {}
|
||||
>recordsOfRecordsOrEmpty.propA : {} | RecordOfRecordsOrEmpty
|
||||
>recordsOfRecordsOrEmpty : RecordOfRecordsOrEmpty
|
||||
>propA : {} | RecordOfRecordsOrEmpty
|
||||
>{...(foo !== undefined ? {foo} : {})} : { foo: Record<never, never>; } | {}
|
||||
>(foo !== undefined ? {foo} : {}) : { foo: Record<never, never>; } | {}
|
||||
>foo !== undefined ? {foo} : {} : { foo: Record<never, never>; } | {}
|
||||
>foo !== undefined : boolean
|
||||
>foo : Record<never, never>
|
||||
>undefined : undefined
|
||||
>{foo} : { foo: Record<never, never>; }
|
||||
>foo : Record<never, never>
|
||||
>{} : {}
|
||||
|
||||
recordsOfRecordsOrEmpty.propB = {...(foo && {foo})} // OK
|
||||
>recordsOfRecordsOrEmpty.propB = {...(foo && {foo})} : { foo: Record<never, never>; }
|
||||
>recordsOfRecordsOrEmpty.propB : {} | RecordOfRecordsOrEmpty
|
||||
>recordsOfRecordsOrEmpty : RecordOfRecordsOrEmpty
|
||||
>propB : {} | RecordOfRecordsOrEmpty
|
||||
>{...(foo && {foo})} : { foo: Record<never, never>; }
|
||||
>(foo && {foo}) : { foo: Record<never, never>; }
|
||||
>foo && {foo} : { foo: Record<never, never>; }
|
||||
>foo : Record<never, never>
|
||||
>{foo} : { foo: Record<never, never>; }
|
||||
>foo : Record<never, never>
|
||||
|
||||
recordsOfRecordsOrEmpty.propC = {...(foo !== undefined && {foo})} // OK
|
||||
>recordsOfRecordsOrEmpty.propC = {...(foo !== undefined && {foo})} : { foo: Record<never, never>; } | {}
|
||||
>recordsOfRecordsOrEmpty.propC : {} | RecordOfRecordsOrEmpty
|
||||
>recordsOfRecordsOrEmpty : RecordOfRecordsOrEmpty
|
||||
>propC : {} | RecordOfRecordsOrEmpty
|
||||
>{...(foo !== undefined && {foo})} : { foo: Record<never, never>; } | {}
|
||||
>(foo !== undefined && {foo}) : false | { foo: Record<never, never>; }
|
||||
>foo !== undefined && {foo} : false | { foo: Record<never, never>; }
|
||||
>foo !== undefined : boolean
|
||||
>foo : Record<never, never>
|
||||
>undefined : undefined
|
||||
>{foo} : { foo: Record<never, never>; }
|
||||
>foo : Record<never, never>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// @strict: true
|
||||
const foo: Record<never, never> = {} // OK
|
||||
|
||||
interface RecordOfRecords extends Record<keyof any, RecordOfRecords> {}
|
||||
const recordOfRecords: RecordOfRecords = {}
|
||||
recordOfRecords.propA = {...(foo !== undefined ? {foo} : {})} // OK
|
||||
recordOfRecords.propB = {...(foo && {foo})} // OK
|
||||
recordOfRecords.propC = {...(foo !== undefined && {foo})} // error'd in 3.7 beta, should be OK
|
||||
|
||||
interface RecordOfRecordsOrEmpty extends Record<keyof any, RecordOfRecordsOrEmpty | {}> {}
|
||||
const recordsOfRecordsOrEmpty: RecordOfRecordsOrEmpty = {}
|
||||
recordsOfRecordsOrEmpty.propA = {...(foo !== undefined ? {foo} : {})} // OK
|
||||
recordsOfRecordsOrEmpty.propB = {...(foo && {foo})} // OK
|
||||
recordsOfRecordsOrEmpty.propC = {...(foo !== undefined && {foo})} // OK
|
Loading…
Reference in a new issue