Revert spread-falsy-union/fix spread of primitive

Turns out partialising falsy unions wasn't needed -- I was just
returning the wrong thing when spreading primitives.
This commit is contained in:
Nathan Shively-Sanders 2017-09-15 16:11:41 -07:00
parent 0197357e31
commit cb8d9d6143
8 changed files with 92 additions and 102 deletions

View File

@ -7846,7 +7846,6 @@ namespace ts {
* and right = the new element to be spread.
*/
function getSpreadType(left: Type, right: Type): Type {
let truthyRight: Type;
if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) {
return anyType;
}
@ -7860,16 +7859,13 @@ namespace ts {
return mapType(left, t => getSpreadType(t, right));
}
if (right.flags & TypeFlags.Union) {
truthyRight = getTruthyTypeFromFalsyUnion(right as UnionType);
if (!truthyRight || truthyRight.flags & TypeFlags.Union) {
return mapType(right, t => getSpreadType(left, t));
}
else {
right = truthyRight;
}
return mapType(right, t => getSpreadType(left, t));
}
if (right.flags & (TypeFlags.NonPrimitive | TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.EnumLike)) {
return emptyObjectType;
if (right.flags & TypeFlags.NonPrimitive) {
return nonPrimitiveType;
}
if (right.flags & (TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.EnumLike)) {
return left;
}
const members = createSymbolTable();
@ -7893,7 +7889,7 @@ namespace ts {
skippedPrivateMembers.set(rightProp.escapedName, true);
}
else if (!isClassMethod(rightProp) && !isSetterWithoutGetter) {
members.set(rightProp.escapedName, getSymbolOfSpreadProperty(rightProp, !!truthyRight));
members.set(rightProp.escapedName, getNonReadonlySymbol(rightProp));
}
}
@ -7918,22 +7914,19 @@ namespace ts {
}
}
else {
members.set(leftProp.escapedName, getSymbolOfSpreadProperty(leftProp, /*makeOptional*/ false));
members.set(leftProp.escapedName, getNonReadonlySymbol(leftProp));
}
}
return createAnonymousType(undefined, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
}
function getSymbolOfSpreadProperty(prop: Symbol, makeOptional: boolean) {
if (!isReadonlySymbol(prop) && (!makeOptional || prop.flags & SymbolFlags.Optional)) {
function getNonReadonlySymbol(prop: Symbol) {
if (!isReadonlySymbol(prop)) {
return prop;
}
const flags = SymbolFlags.Property | (makeOptional ? SymbolFlags.Optional : prop.flags & SymbolFlags.Optional);
const flags = SymbolFlags.Property | (prop.flags & SymbolFlags.Optional);
const result = createSymbol(flags, prop.escapedName);
result.type = getTypeOfSymbol(prop);
if (makeOptional) {
result.type = getUnionType([result.type, undefinedType]);
}
result.declarations = prop.declarations;
result.syntheticOrigin = prop;
return result;
@ -7943,13 +7936,6 @@ namespace ts {
return prop.flags & SymbolFlags.Method && find(prop.declarations, decl => isClassLike(decl.parent));
}
function getTruthyTypeFromFalsyUnion(type: UnionType): Type | undefined {
const truthy = removeDefinitelyFalsyTypes(type);
if (truthy !== type) {
return truthy;
}
}
function createLiteralType(flags: TypeFlags, value: string | number, symbol: Symbol) {
const type = <LiteralType>createType(flags);
type.symbol = symbol;

View File

@ -247,7 +247,7 @@ function from16326(this: { header: Header }, header: Header, authToken: string):
>Header : Header
return {
>{ ...this.header, ...header, ...authToken && { authToken } } : { authToken: string; head: string; body: string; }
>{ ...this.header, ...header, ...authToken && { authToken } } : { head: string; body: string; authToken: string; } | { authToken: string; head: string; body: string; }
...this.header,
>this.header : Header
@ -280,9 +280,9 @@ function conditionalSpreadBoolean(b: boolean) : { x: number, y: number } {
>13 : 13
o = {
>o = { ...o, ...b && { x: 14 } } : { x: number; y: number; }
>o = { ...o, ...b && { x: 14 } } : { x: number; y: number; } | { x: number; y: number; }
>o : { x: number; y: number; }
>{ ...o, ...b && { x: 14 } } : { x: number; y: number; }
>{ ...o, ...b && { x: 14 } } : { x: number; y: number; } | { x: number; y: number; }
...o,
>o : { x: number; y: number; }
@ -295,8 +295,8 @@ function conditionalSpreadBoolean(b: boolean) : { x: number, y: number } {
>14 : 14
}
let o2 = { ...b && { x: 21 }}
>o2 : { x?: number | undefined; }
>{ ...b && { x: 21 }} : { x?: number | undefined; }
>o2 : {} | { x: number; }
>{ ...b && { x: 21 }} : {} | { x: number; }
>b && { x: 21 } : false | { x: number; }
>b : boolean
>{ x: 21 } : { x: number; }
@ -321,9 +321,9 @@ function conditionalSpreadNumber(nt: number): { x: number, y: number } {
>16 : 16
o = {
>o = { ...o, ...nt && { x: nt } } : { x: number; y: number; }
>o = { ...o, ...nt && { x: nt } } : { x: number; y: number; } | { x: number; y: number; }
>o : { x: number; y: number; }
>{ ...o, ...nt && { x: nt } } : { x: number; y: number; }
>{ ...o, ...nt && { x: nt } } : { x: number; y: number; } | { x: number; y: number; }
...o,
>o : { x: number; y: number; }
@ -336,8 +336,8 @@ function conditionalSpreadNumber(nt: number): { x: number, y: number } {
>nt : number
}
let o2 = { ...nt && { x: nt }}
>o2 : { x?: number | undefined; }
>{ ...nt && { x: nt }} : { x?: number | undefined; }
>o2 : {} | { x: number; }
>{ ...nt && { x: nt }} : {} | { x: number; }
>nt && { x: nt } : 0 | { x: number; }
>nt : number
>{ x: nt } : { x: number; }
@ -362,9 +362,9 @@ function conditionalSpreadString(st: string): { x: string, y: number } {
>17 : 17
o = {
>o = { ...o, ...st && { x: st } } : { x: string; y: number; }
>o = { ...o, ...st && { x: st } } : { x: string; y: number; } | { x: string; y: number; }
>o : { x: string; y: number; }
>{ ...o, ...st && { x: st } } : { x: string; y: number; }
>{ ...o, ...st && { x: st } } : { x: string; y: number; } | { x: string; y: number; }
...o,
>o : { x: string; y: number; }
@ -377,8 +377,8 @@ function conditionalSpreadString(st: string): { x: string, y: number } {
>st : string
}
let o2 = { ...st && { x: st }}
>o2 : { x?: string | undefined; }
>{ ...st && { x: st }} : { x?: string | undefined; }
>o2 : {} | { x: string; }
>{ ...st && { x: st }} : {} | { x: string; }
>st && { x: st } : "" | { x: string; }
>st : string
>{ x: st } : { x: string; }
@ -571,8 +571,8 @@ let shortCutted: { a: number, b: string } = { ...o, a }
// non primitive
let spreadNonPrimitive = { ...<object>{}};
>spreadNonPrimitive : {}
>{ ...<object>{}} : {}
>spreadNonPrimitive : object
>{ ...<object>{}} : object
><object>{} : object
>{} : {}

View File

@ -15,7 +15,7 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(38,19): error TS269
tests/cases/conformance/types/spread/objectSpreadNegative.ts(43,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{}' has no compatible call signatures.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(47,12): error TS2339: Property 'b' does not exist on type '{}'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(53,9): error TS2339: Property 'm' does not exist on type '{ p: number; }'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(58,11): error TS2339: Property 'a' does not exist on type '{}'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(58,11): error TS2339: Property 'a' does not exist on type 'object'.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(62,14): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(65,14): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/types/spread/objectSpreadNegative.ts(79,37): error TS2322: Type '{ a: string; b: string; extra: string; }' is not assignable to type 'A'.
@ -117,7 +117,7 @@ tests/cases/conformance/types/spread/objectSpreadNegative.ts(84,7): error TS2322
let spreadObj = { ...obj };
spreadObj.a; // error 'a' is not in {}
~
!!! error TS2339: Property 'a' does not exist on type '{}'.
!!! error TS2339: Property 'a' does not exist on type 'object'.
// generics
function f<T, U>(t: T, u: U) {

View File

@ -2,20 +2,20 @@
declare const undefinedUnion: { a: number } | undefined;
declare const nullUnion: { b: number } | null;
var o1: { a?: number | undefined };
var o1: {} | { a: number };
var o1 = { ...undefinedUnion };
var o2: { b?: number | undefined };
var o2: {} | { b: number };
var o2 = { ...nullUnion };
var o3: { a?: number | undefined, b?: number | undefined };
var o3: {} | { a: number } | { b: number } | { a: number, b: number };
var o3 = { ...undefinedUnion, ...nullUnion };
var o3 = { ...nullUnion, ...undefinedUnion };
var o4: { a?: number | undefined };
var o4: {} | { a: number };
var o4 = { ...undefinedUnion, ...undefinedUnion };
var o5: { b?: number | undefined };
var o5: {} | { b: number };
var o5 = { ...nullUnion, ...nullUnion };

View File

@ -7,26 +7,28 @@ declare const nullUnion: { b: number } | null;
>nullUnion : Symbol(nullUnion, Decl(spreadUnion2.ts, 1, 13))
>b : Symbol(b, Decl(spreadUnion2.ts, 1, 26))
var o1: { a?: number | undefined };
var o1: {} | { a: number };
>o1 : Symbol(o1, Decl(spreadUnion2.ts, 3, 3), Decl(spreadUnion2.ts, 4, 3))
>a : Symbol(a, Decl(spreadUnion2.ts, 3, 9))
>a : Symbol(a, Decl(spreadUnion2.ts, 3, 14))
var o1 = { ...undefinedUnion };
>o1 : Symbol(o1, Decl(spreadUnion2.ts, 3, 3), Decl(spreadUnion2.ts, 4, 3))
>undefinedUnion : Symbol(undefinedUnion, Decl(spreadUnion2.ts, 0, 13))
var o2: { b?: number | undefined };
var o2: {} | { b: number };
>o2 : Symbol(o2, Decl(spreadUnion2.ts, 6, 3), Decl(spreadUnion2.ts, 7, 3))
>b : Symbol(b, Decl(spreadUnion2.ts, 6, 9))
>b : Symbol(b, Decl(spreadUnion2.ts, 6, 14))
var o2 = { ...nullUnion };
>o2 : Symbol(o2, Decl(spreadUnion2.ts, 6, 3), Decl(spreadUnion2.ts, 7, 3))
>nullUnion : Symbol(nullUnion, Decl(spreadUnion2.ts, 1, 13))
var o3: { a?: number | undefined, b?: number | undefined };
var o3: {} | { a: number } | { b: number } | { a: number, b: number };
>o3 : Symbol(o3, Decl(spreadUnion2.ts, 9, 3), Decl(spreadUnion2.ts, 10, 3), Decl(spreadUnion2.ts, 11, 3))
>a : Symbol(a, Decl(spreadUnion2.ts, 9, 9))
>b : Symbol(b, Decl(spreadUnion2.ts, 9, 33))
>a : Symbol(a, Decl(spreadUnion2.ts, 9, 14))
>b : Symbol(b, Decl(spreadUnion2.ts, 9, 30))
>a : Symbol(a, Decl(spreadUnion2.ts, 9, 46))
>b : Symbol(b, Decl(spreadUnion2.ts, 9, 57))
var o3 = { ...undefinedUnion, ...nullUnion };
>o3 : Symbol(o3, Decl(spreadUnion2.ts, 9, 3), Decl(spreadUnion2.ts, 10, 3), Decl(spreadUnion2.ts, 11, 3))
@ -38,18 +40,18 @@ var o3 = { ...nullUnion, ...undefinedUnion };
>nullUnion : Symbol(nullUnion, Decl(spreadUnion2.ts, 1, 13))
>undefinedUnion : Symbol(undefinedUnion, Decl(spreadUnion2.ts, 0, 13))
var o4: { a?: number | undefined };
var o4: {} | { a: number };
>o4 : Symbol(o4, Decl(spreadUnion2.ts, 13, 3), Decl(spreadUnion2.ts, 14, 3))
>a : Symbol(a, Decl(spreadUnion2.ts, 13, 9))
>a : Symbol(a, Decl(spreadUnion2.ts, 13, 14))
var o4 = { ...undefinedUnion, ...undefinedUnion };
>o4 : Symbol(o4, Decl(spreadUnion2.ts, 13, 3), Decl(spreadUnion2.ts, 14, 3))
>undefinedUnion : Symbol(undefinedUnion, Decl(spreadUnion2.ts, 0, 13))
>undefinedUnion : Symbol(undefinedUnion, Decl(spreadUnion2.ts, 0, 13))
var o5: { b?: number | undefined };
var o5: {} | { b: number };
>o5 : Symbol(o5, Decl(spreadUnion2.ts, 16, 3), Decl(spreadUnion2.ts, 17, 3))
>b : Symbol(b, Decl(spreadUnion2.ts, 16, 9))
>b : Symbol(b, Decl(spreadUnion2.ts, 16, 14))
var o5 = { ...nullUnion, ...nullUnion };
>o5 : Symbol(o5, Decl(spreadUnion2.ts, 16, 3), Decl(spreadUnion2.ts, 17, 3))

View File

@ -8,58 +8,60 @@ declare const nullUnion: { b: number } | null;
>b : number
>null : null
var o1: { a?: number | undefined };
>o1 : { a?: number | undefined; }
>a : number | undefined
var o1: {} | { a: number };
>o1 : {} | { a: number; }
>a : number
var o1 = { ...undefinedUnion };
>o1 : { a?: number | undefined; }
>{ ...undefinedUnion } : { a?: number | undefined; }
>o1 : {} | { a: number; }
>{ ...undefinedUnion } : {} | { a: number; }
>undefinedUnion : { a: number; } | undefined
var o2: { b?: number | undefined };
>o2 : { b?: number | undefined; }
>b : number | undefined
var o2: {} | { b: number };
>o2 : {} | { b: number; }
>b : number
var o2 = { ...nullUnion };
>o2 : { b?: number | undefined; }
>{ ...nullUnion } : { b?: number | undefined; }
>o2 : {} | { b: number; }
>{ ...nullUnion } : {} | { b: number; }
>nullUnion : { b: number; } | null
var o3: { a?: number | undefined, b?: number | undefined };
>o3 : { a?: number | undefined; b?: number | undefined; }
>a : number | undefined
>b : number | undefined
var o3: {} | { a: number } | { b: number } | { a: number, b: number };
>o3 : {} | { a: number; } | { b: number; } | { a: number; b: number; }
>a : number
>b : number
>a : number
>b : number
var o3 = { ...undefinedUnion, ...nullUnion };
>o3 : { a?: number | undefined; b?: number | undefined; }
>{ ...undefinedUnion, ...nullUnion } : { b?: number | undefined; a?: number | undefined; }
>o3 : {} | { a: number; } | { b: number; } | { a: number; b: number; }
>{ ...undefinedUnion, ...nullUnion } : {} | { b: number; } | { a: number; } | { b: number; a: number; }
>undefinedUnion : { a: number; } | undefined
>nullUnion : { b: number; } | null
var o3 = { ...nullUnion, ...undefinedUnion };
>o3 : { a?: number | undefined; b?: number | undefined; }
>{ ...nullUnion, ...undefinedUnion } : { a?: number | undefined; b?: number | undefined; }
>o3 : {} | { a: number; } | { b: number; } | { a: number; b: number; }
>{ ...nullUnion, ...undefinedUnion } : {} | { a: number; } | { b: number; } | { a: number; b: number; }
>nullUnion : { b: number; } | null
>undefinedUnion : { a: number; } | undefined
var o4: { a?: number | undefined };
>o4 : { a?: number | undefined; }
>a : number | undefined
var o4: {} | { a: number };
>o4 : {} | { a: number; }
>a : number
var o4 = { ...undefinedUnion, ...undefinedUnion };
>o4 : { a?: number | undefined; }
>{ ...undefinedUnion, ...undefinedUnion } : { a?: number | undefined; }
>o4 : {} | { a: number; }
>{ ...undefinedUnion, ...undefinedUnion } : {} | { a: number; } | { a: number; } | { a: number; }
>undefinedUnion : { a: number; } | undefined
>undefinedUnion : { a: number; } | undefined
var o5: { b?: number | undefined };
>o5 : { b?: number | undefined; }
>b : number | undefined
var o5: {} | { b: number };
>o5 : {} | { b: number; }
>b : number
var o5 = { ...nullUnion, ...nullUnion };
>o5 : { b?: number | undefined; }
>{ ...nullUnion, ...nullUnion } : { b?: number | undefined; }
>o5 : {} | { b: number; }
>{ ...nullUnion, ...nullUnion } : {} | { b: number; } | { b: number; } | { b: number; }
>nullUnion : { b: number; } | null
>nullUnion : { b: number; } | null

View File

@ -1,9 +1,9 @@
tests/cases/conformance/types/spread/spreadUnion3.ts(2,5): error TS2322: Type '{ y: string | number; }' is not assignable to type '{ y: string; }'.
Types of property 'y' are incompatible.
Type 'string | number' is not assignable to type 'string'.
tests/cases/conformance/types/spread/spreadUnion3.ts(2,5): error TS2322: Type '{ y: number; } | { y: string; }' is not assignable to type '{ y: string; }'.
Type '{ y: number; }' is not assignable to type '{ y: string; }'.
Types of property 'y' are incompatible.
Type 'number' is not assignable to type 'string'.
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(9,23): error TS2339: Property 'a' does not exist on type '{} | {} | { a: number; }'.
Property 'a' does not exist on type '{}'.
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.
@ -12,9 +12,9 @@ tests/cases/conformance/types/spread/spreadUnion3.ts(18,11): error TS2698: Sprea
function f(x: { y: string } | undefined): { y: string } {
return { y: 123, ...x } // y: string | number
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2322: Type '{ y: string | number; }' is not assignable to type '{ y: string; }'.
!!! error TS2322: Types of property 'y' are incompatible.
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
!!! error TS2322: Type '{ y: number; } | { y: string; }' is not assignable to type '{ y: string; }'.
!!! error TS2322: Type '{ y: number; }' is not assignable to type '{ y: string; }'.
!!! error TS2322: Types of property 'y' are incompatible.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
}
f(undefined)
@ -23,9 +23,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 TS2322: Type 'number | undefined' is not assignable to type 'number'.
!!! error TS2322: Type 'undefined' is not assignable to type 'number'.
~
!!! error TS2339: Property 'a' does not exist on type '{} | {} | { a: number; }'.
!!! error TS2339: Property 'a' does not exist on type '{}'.
}
g()
g(undefined)

View File

@ -3,19 +3,19 @@
declare const undefinedUnion: { a: number } | undefined;
declare const nullUnion: { b: number } | null;
var o1: { a?: number | undefined };
var o1: {} | { a: number };
var o1 = { ...undefinedUnion };
var o2: { b?: number | undefined };
var o2: {} | { b: number };
var o2 = { ...nullUnion };
var o3: { a?: number | undefined, b?: number | undefined };
var o3: {} | { a: number } | { b: number } | { a: number, b: number };
var o3 = { ...undefinedUnion, ...nullUnion };
var o3 = { ...nullUnion, ...undefinedUnion };
var o4: { a?: number | undefined };
var o4: {} | { a: number };
var o4 = { ...undefinedUnion, ...undefinedUnion };
var o5: { b?: number | undefined };
var o5: {} | { b: number };
var o5 = { ...nullUnion, ...nullUnion };