Merge pull request #16306 from Microsoft/fix-nullable-filtering-in-spreads

Fix nullable filtering in spreads
This commit is contained in:
Nathan Shively-Sanders
2017-06-06 15:00:48 -07:00
committed by GitHub
11 changed files with 144 additions and 69 deletions

View File

@@ -7642,11 +7642,9 @@ namespace ts {
if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) {
return anyType;
}
left = filterType(left, t => !(t.flags & TypeFlags.Nullable));
if (left.flags & TypeFlags.Never) {
return right;
}
right = filterType(right, t => !(t.flags & TypeFlags.Nullable));
if (right.flags & TypeFlags.Never) {
return left;
}

View File

@@ -1,4 +1,4 @@
=== tests/cases/compiler/spreadUnion.ts ===
=== tests/cases/conformance/types/spread/spreadUnion.ts ===
var union: { a: number } | { b: string };
>union : Symbol(union, Decl(spreadUnion.ts, 0, 3))
>a : Symbol(a, Decl(spreadUnion.ts, 0, 12))

View File

@@ -1,4 +1,4 @@
=== tests/cases/compiler/spreadUnion.ts ===
=== tests/cases/conformance/types/spread/spreadUnion.ts ===
var union: { a: number } | { b: string };
>union : { a: number; } | { b: string; }
>a : number

View File

@@ -3,25 +3,25 @@ declare const undefinedUnion: { a: number } | undefined;
declare const nullUnion: { b: number } | null;
declare const nullAndUndefinedUnion: null | undefined;
var o1: { a: number };
var o1: {} | { a: number };
var o1 = { ...undefinedUnion };
var o2: { b: number };
var o2: {} | { b: number };
var o2 = { ...nullUnion };
var o3: { a: number, b: number };
var o3: {} | { b: number } | { a: number } | { a: number, b: number };
var o3 = { ...undefinedUnion, ...nullUnion };
var o3 = { ...nullUnion, ...undefinedUnion };
var o4: { a: number };
var o4: {} | { a: number };
var o4 = { ...undefinedUnion, ...undefinedUnion };
var o5: { b: number };
var o5: {} | { b: number };
var o5 = { ...nullUnion, ...nullUnion };
var o6: { };
var o6 = { ...nullAndUndefinedUnion, ...nullAndUndefinedUnion };
var o6 = { ...nullAndUndefinedUnion };
var o7 = { ...nullAndUndefinedUnion };
//// [spreadUnion2.js]
var __assign = (this && this.__assign) || Object.assign || function(t) {
@@ -43,6 +43,5 @@ var o4;
var o4 = __assign({}, undefinedUnion, undefinedUnion);
var o5;
var o5 = __assign({}, nullUnion, nullUnion);
var o6;
var o6 = __assign({}, nullAndUndefinedUnion, nullAndUndefinedUnion);
var o6 = __assign({}, nullAndUndefinedUnion);
var o7 = __assign({}, nullAndUndefinedUnion);

View File

@@ -1,4 +1,4 @@
=== tests/cases/compiler/spreadUnion2.ts ===
=== tests/cases/conformance/types/spread/spreadUnion2.ts ===
declare const undefinedUnion: { a: number } | undefined;
>undefinedUnion : Symbol(undefinedUnion, Decl(spreadUnion2.ts, 0, 13))
>a : Symbol(a, Decl(spreadUnion2.ts, 0, 31))
@@ -10,26 +10,28 @@ declare const nullUnion: { b: number } | null;
declare const nullAndUndefinedUnion: null | undefined;
>nullAndUndefinedUnion : Symbol(nullAndUndefinedUnion, Decl(spreadUnion2.ts, 2, 13))
var o1: { a: number };
var o1: {} | { a: number };
>o1 : Symbol(o1, Decl(spreadUnion2.ts, 4, 3), Decl(spreadUnion2.ts, 5, 3))
>a : Symbol(a, Decl(spreadUnion2.ts, 4, 9))
>a : Symbol(a, Decl(spreadUnion2.ts, 4, 14))
var o1 = { ...undefinedUnion };
>o1 : Symbol(o1, Decl(spreadUnion2.ts, 4, 3), Decl(spreadUnion2.ts, 5, 3))
>undefinedUnion : Symbol(undefinedUnion, Decl(spreadUnion2.ts, 0, 13))
var o2: { b: number };
var o2: {} | { b: number };
>o2 : Symbol(o2, Decl(spreadUnion2.ts, 7, 3), Decl(spreadUnion2.ts, 8, 3))
>b : Symbol(b, Decl(spreadUnion2.ts, 7, 9))
>b : Symbol(b, Decl(spreadUnion2.ts, 7, 14))
var o2 = { ...nullUnion };
>o2 : Symbol(o2, Decl(spreadUnion2.ts, 7, 3), Decl(spreadUnion2.ts, 8, 3))
>nullUnion : Symbol(nullUnion, Decl(spreadUnion2.ts, 1, 13))
var o3: { a: number, b: number };
var o3: {} | { b: number } | { a: number } | { a: number, b: number };
>o3 : Symbol(o3, Decl(spreadUnion2.ts, 10, 3), Decl(spreadUnion2.ts, 11, 3), Decl(spreadUnion2.ts, 12, 3))
>a : Symbol(a, Decl(spreadUnion2.ts, 10, 9))
>b : Symbol(b, Decl(spreadUnion2.ts, 10, 20))
>b : Symbol(b, Decl(spreadUnion2.ts, 10, 14))
>a : Symbol(a, Decl(spreadUnion2.ts, 10, 30))
>a : Symbol(a, Decl(spreadUnion2.ts, 10, 46))
>b : Symbol(b, Decl(spreadUnion2.ts, 10, 57))
var o3 = { ...undefinedUnion, ...nullUnion };
>o3 : Symbol(o3, Decl(spreadUnion2.ts, 10, 3), Decl(spreadUnion2.ts, 11, 3), Decl(spreadUnion2.ts, 12, 3))
@@ -41,33 +43,30 @@ var o3 = { ...nullUnion, ...undefinedUnion };
>nullUnion : Symbol(nullUnion, Decl(spreadUnion2.ts, 1, 13))
>undefinedUnion : Symbol(undefinedUnion, Decl(spreadUnion2.ts, 0, 13))
var o4: { a: number };
var o4: {} | { a: number };
>o4 : Symbol(o4, Decl(spreadUnion2.ts, 14, 3), Decl(spreadUnion2.ts, 15, 3))
>a : Symbol(a, Decl(spreadUnion2.ts, 14, 9))
>a : Symbol(a, Decl(spreadUnion2.ts, 14, 14))
var o4 = { ...undefinedUnion, ...undefinedUnion };
>o4 : Symbol(o4, Decl(spreadUnion2.ts, 14, 3), Decl(spreadUnion2.ts, 15, 3))
>undefinedUnion : Symbol(undefinedUnion, Decl(spreadUnion2.ts, 0, 13))
>undefinedUnion : Symbol(undefinedUnion, Decl(spreadUnion2.ts, 0, 13))
var o5: { b: number };
var o5: {} | { b: number };
>o5 : Symbol(o5, Decl(spreadUnion2.ts, 17, 3), Decl(spreadUnion2.ts, 18, 3))
>b : Symbol(b, Decl(spreadUnion2.ts, 17, 9))
>b : Symbol(b, Decl(spreadUnion2.ts, 17, 14))
var o5 = { ...nullUnion, ...nullUnion };
>o5 : Symbol(o5, Decl(spreadUnion2.ts, 17, 3), Decl(spreadUnion2.ts, 18, 3))
>nullUnion : Symbol(nullUnion, Decl(spreadUnion2.ts, 1, 13))
>nullUnion : Symbol(nullUnion, Decl(spreadUnion2.ts, 1, 13))
var o6: { };
>o6 : Symbol(o6, Decl(spreadUnion2.ts, 20, 3), Decl(spreadUnion2.ts, 21, 3), Decl(spreadUnion2.ts, 22, 3))
var o6 = { ...nullAndUndefinedUnion, ...nullAndUndefinedUnion };
>o6 : Symbol(o6, Decl(spreadUnion2.ts, 20, 3), Decl(spreadUnion2.ts, 21, 3), Decl(spreadUnion2.ts, 22, 3))
>o6 : Symbol(o6, Decl(spreadUnion2.ts, 20, 3))
>nullAndUndefinedUnion : Symbol(nullAndUndefinedUnion, Decl(spreadUnion2.ts, 2, 13))
>nullAndUndefinedUnion : Symbol(nullAndUndefinedUnion, Decl(spreadUnion2.ts, 2, 13))
var o6 = { ...nullAndUndefinedUnion };
>o6 : Symbol(o6, Decl(spreadUnion2.ts, 20, 3), Decl(spreadUnion2.ts, 21, 3), Decl(spreadUnion2.ts, 22, 3))
var o7 = { ...nullAndUndefinedUnion };
>o7 : Symbol(o7, Decl(spreadUnion2.ts, 21, 3))
>nullAndUndefinedUnion : Symbol(nullAndUndefinedUnion, Decl(spreadUnion2.ts, 2, 13))

View File

@@ -1,4 +1,4 @@
=== tests/cases/compiler/spreadUnion2.ts ===
=== tests/cases/conformance/types/spread/spreadUnion2.ts ===
declare const undefinedUnion: { a: number } | undefined;
>undefinedUnion : { a: number; } | undefined
>a : number
@@ -12,72 +12,71 @@ declare const nullAndUndefinedUnion: null | undefined;
>nullAndUndefinedUnion : null | undefined
>null : null
var o1: { a: number };
>o1 : { a: number; }
var o1: {} | { a: number };
>o1 : {} | { a: number; }
>a : number
var o1 = { ...undefinedUnion };
>o1 : { a: number; }
>{ ...undefinedUnion } : { a: number; }
>o1 : {} | { a: number; }
>{ ...undefinedUnion } : {} | { a: number; }
>undefinedUnion : { a: number; } | undefined
var o2: { b: number };
>o2 : { b: number; }
var o2: {} | { b: number };
>o2 : {} | { b: number; }
>b : number
var o2 = { ...nullUnion };
>o2 : { b: number; }
>{ ...nullUnion } : { b: number; }
>o2 : {} | { b: number; }
>{ ...nullUnion } : {} | { b: number; }
>nullUnion : { b: number; } | null
var o3: { a: number, b: number };
>o3 : { a: number; b: number; }
var o3: {} | { b: number } | { a: number } | { a: number, b: number };
>o3 : {} | { b: number; } | { a: number; } | { a: number; b: number; }
>b : number
>a : number
>a : number
>b : number
var o3 = { ...undefinedUnion, ...nullUnion };
>o3 : { a: number; b: number; }
>{ ...undefinedUnion, ...nullUnion } : { b: number; a: number; }
>o3 : {} | { b: number; } | { a: 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; b: number; }
>{ ...nullUnion, ...undefinedUnion } : { a: number; b: number; }
>o3 : {} | { b: number; } | { a: 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 };
>o4 : { a: number; }
var o4: {} | { a: number };
>o4 : {} | { a: number; }
>a : number
var o4 = { ...undefinedUnion, ...undefinedUnion };
>o4 : { a: number; }
>{ ...undefinedUnion, ...undefinedUnion } : { a: number; }
>o4 : {} | { a: number; }
>{ ...undefinedUnion, ...undefinedUnion } : {} | { a: number; } | { a: number; } | { a: number; }
>undefinedUnion : { a: number; } | undefined
>undefinedUnion : { a: number; } | undefined
var o5: { b: number };
>o5 : { b: number; }
var o5: {} | { b: number };
>o5 : {} | { b: number; }
>b : number
var o5 = { ...nullUnion, ...nullUnion };
>o5 : { b: number; }
>{ ...nullUnion, ...nullUnion } : { b: number; }
>o5 : {} | { b: number; }
>{ ...nullUnion, ...nullUnion } : {} | { b: number; } | { b: number; } | { b: number; }
>nullUnion : { b: number; } | null
>nullUnion : { b: number; } | null
var o6: { };
>o6 : {}
var o6 = { ...nullAndUndefinedUnion, ...nullAndUndefinedUnion };
>o6 : {}
>{ ...nullAndUndefinedUnion, ...nullAndUndefinedUnion } : {}
>o6 : {} | {} | {} | {}
>{ ...nullAndUndefinedUnion, ...nullAndUndefinedUnion } : {} | {} | {} | {}
>nullAndUndefinedUnion : null | undefined
>nullAndUndefinedUnion : null | undefined
var o6 = { ...nullAndUndefinedUnion };
>o6 : {}
>{ ...nullAndUndefinedUnion } : {}
var o7 = { ...nullAndUndefinedUnion };
>o7 : {} | {}
>{ ...nullAndUndefinedUnion } : {} | {}
>nullAndUndefinedUnion : null | undefined

View File

@@ -0,0 +1,31 @@
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,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 (2 errors) ====
function f(x: { y: string } | undefined): { y: string } {
return { y: 123, ...x } // y: string | number
~~~~~~~~~~~~~~~~~~~~~~~
!!! 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)
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 '{} | {} | { a: number; }'.
!!! error TS2339: Property 'a' does not exist on type '{}'.
}
g()
g(undefined)
g(null)

View File

@@ -0,0 +1,36 @@
//// [spreadUnion3.ts]
function f(x: { y: string } | undefined): { y: string } {
return { y: 123, ...x } // y: string | number
}
f(undefined)
function g(t?: { a: number } | null): void {
let b = { ...t };
let c: number = b.a; // might not have 'a'
}
g()
g(undefined)
g(null)
//// [spreadUnion3.js]
var __assign = (this && this.__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;
};
function f(x) {
return __assign({ y: 123 }, x); // y: string | number
}
f(undefined);
function g(t) {
var b = __assign({}, t);
var c = b.a; // might not have 'a'
}
g();
g(undefined);
g(null);

View File

@@ -4,22 +4,21 @@ declare const undefinedUnion: { a: number } | undefined;
declare const nullUnion: { b: number } | null;
declare const nullAndUndefinedUnion: null | undefined;
var o1: { a: number };
var o1: {} | { a: number };
var o1 = { ...undefinedUnion };
var o2: { b: number };
var o2: {} | { b: number };
var o2 = { ...nullUnion };
var o3: { a: number, b: number };
var o3: {} | { b: number } | { a: number } | { a: number, b: number };
var o3 = { ...undefinedUnion, ...nullUnion };
var o3 = { ...nullUnion, ...undefinedUnion };
var o4: { a: number };
var o4: {} | { a: number };
var o4 = { ...undefinedUnion, ...undefinedUnion };
var o5: { b: number };
var o5: {} | { b: number };
var o5 = { ...nullUnion, ...nullUnion };
var o6: { };
var o6 = { ...nullAndUndefinedUnion, ...nullAndUndefinedUnion };
var o6 = { ...nullAndUndefinedUnion };
var o7 = { ...nullAndUndefinedUnion };

View File

@@ -0,0 +1,14 @@
// @strictNullChecks: true
function f(x: { y: string } | undefined): { y: string } {
return { y: 123, ...x } // y: string | number
}
f(undefined)
function g(t?: { a: number } | null): void {
let b = { ...t };
let c: number = b.a; // might not have 'a'
}
g()
g(undefined)
g(null)