Narrow to any primitive or object and update tests

This commit is contained in:
Jack Williams
2019-01-25 09:41:34 +00:00
parent 1f2338bd78
commit 36cc154985
6 changed files with 554 additions and 10 deletions
+8 -2
View File
@@ -16018,8 +16018,14 @@ namespace ts {
assumeTrue = !assumeTrue;
}
const valueType = getTypeOfExpression(value);
if ((type.flags & TypeFlags.Unknown) && (operator === SyntaxKind.EqualsEqualsEqualsToken) && (valueType.flags & TypeFlags.Unit)) {
return assumeTrue ? valueType : type;
if ((type.flags & TypeFlags.Unknown) && (operator === SyntaxKind.EqualsEqualsEqualsToken) && assumeTrue) {
if (valueType.flags & TypeFlags.Primitive || valueType.flags & TypeFlags.NonPrimitive) {
return valueType;
}
if (valueType.flags & TypeFlags.Object) {
return nonPrimitiveType;
}
return type;
}
if (valueType.flags & TypeFlags.Nullable) {
if (!strictNullChecks) {
+108 -1
View File
@@ -31,7 +31,6 @@ if (u === symb) {
if (!(u === 42)) {
type A = isTrue<isUnknown<typeof u>>
}
if (u !== 42) {
@@ -49,6 +48,71 @@ if (u == true) {
if (u == Object) {
type E = isTrue<isUnknown<typeof u>>
}
declare const aString: string;
declare const aBoolean: boolean;
declare const aNumber: number;
declare const anObject: object;
declare const anObjectLiteral: { x: number };
declare const aUnion: { x: number } | { y: string };
declare const anIntersection: { x: number } & { y: string };
declare const aFunction: () => number;
if (u === aString) {
let uString: string = u;
}
if (u === aBoolean) {
let uString: boolean = u;
}
if (u === aNumber) {
let uNumber: number = u;
}
if (u === anObject) {
let uObject: object = u;
}
if (u === anObjectLiteral) {
let uObjectLiteral: object = u;
}
if (u === aUnion) {
type unionDoesNotNarrow = isTrue<isUnknown<typeof u>>
}
if (u === anIntersection) {
type intersectionDoesNotNarrow = isTrue<isUnknown<typeof u>>
}
if (u === aFunction) {
let uFunction: object = u;
}
enum NumberEnum {
A,
B,
C
}
enum StringEnum {
A = "A",
B = "B",
C = "C"
}
if (u === NumberEnum || u === StringEnum) {
let enumObj: object = u;
}
if(u === NumberEnum.A) {
let a: NumberEnum.A = u
}
if(u === StringEnum.B) {
let b: StringEnum.B = u
}
//// [unknownType2.js]
@@ -80,3 +144,46 @@ if (u == true) {
}
if (u == Object) {
}
if (u === aString) {
var uString = u;
}
if (u === aBoolean) {
var uString = u;
}
if (u === aNumber) {
var uNumber = u;
}
if (u === anObject) {
var uObject = u;
}
if (u === anObjectLiteral) {
var uObjectLiteral = u;
}
if (u === aUnion) {
}
if (u === anIntersection) {
}
if (u === aFunction) {
var uFunction = u;
}
var NumberEnum;
(function (NumberEnum) {
NumberEnum[NumberEnum["A"] = 0] = "A";
NumberEnum[NumberEnum["B"] = 1] = "B";
NumberEnum[NumberEnum["C"] = 2] = "C";
})(NumberEnum || (NumberEnum = {}));
var StringEnum;
(function (StringEnum) {
StringEnum["A"] = "A";
StringEnum["B"] = "B";
StringEnum["C"] = "C";
})(StringEnum || (StringEnum = {}));
if (u === NumberEnum || u === StringEnum) {
var enumObj = u;
}
if (u === NumberEnum.A) {
var a = u;
}
if (u === StringEnum.B) {
var b = u;
}
+172 -5
View File
@@ -82,14 +82,13 @@ if (!(u === 42)) {
>isTrue : Symbol(isTrue, Decl(unknownType2.ts, 0, 53))
>isUnknown : Symbol(isUnknown, Decl(unknownType2.ts, 0, 0))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
}
if (u !== 42) {
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
type B = isTrue<isUnknown<typeof u>>
>B : Symbol(B, Decl(unknownType2.ts, 35, 15))
>B : Symbol(B, Decl(unknownType2.ts, 34, 15))
>isTrue : Symbol(isTrue, Decl(unknownType2.ts, 0, 53))
>isUnknown : Symbol(isUnknown, Decl(unknownType2.ts, 0, 0))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
@@ -99,7 +98,7 @@ if (u == 42) {
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
type C = isTrue<isUnknown<typeof u>>
>C : Symbol(C, Decl(unknownType2.ts, 39, 14))
>C : Symbol(C, Decl(unknownType2.ts, 38, 14))
>isTrue : Symbol(isTrue, Decl(unknownType2.ts, 0, 53))
>isUnknown : Symbol(isUnknown, Decl(unknownType2.ts, 0, 0))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
@@ -109,7 +108,7 @@ if (u == true) {
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
type D = isTrue<isUnknown<typeof u>>
>D : Symbol(D, Decl(unknownType2.ts, 43, 16))
>D : Symbol(D, Decl(unknownType2.ts, 42, 16))
>isTrue : Symbol(isTrue, Decl(unknownType2.ts, 0, 53))
>isUnknown : Symbol(isUnknown, Decl(unknownType2.ts, 0, 0))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
@@ -120,9 +119,177 @@ if (u == Object) {
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
type E = isTrue<isUnknown<typeof u>>
>E : Symbol(E, Decl(unknownType2.ts, 47, 18))
>E : Symbol(E, Decl(unknownType2.ts, 46, 18))
>isTrue : Symbol(isTrue, Decl(unknownType2.ts, 0, 53))
>isUnknown : Symbol(isUnknown, Decl(unknownType2.ts, 0, 0))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
}
declare const aString: string;
>aString : Symbol(aString, Decl(unknownType2.ts, 50, 13))
declare const aBoolean: boolean;
>aBoolean : Symbol(aBoolean, Decl(unknownType2.ts, 51, 13))
declare const aNumber: number;
>aNumber : Symbol(aNumber, Decl(unknownType2.ts, 52, 13))
declare const anObject: object;
>anObject : Symbol(anObject, Decl(unknownType2.ts, 53, 13))
declare const anObjectLiteral: { x: number };
>anObjectLiteral : Symbol(anObjectLiteral, Decl(unknownType2.ts, 54, 13))
>x : Symbol(x, Decl(unknownType2.ts, 54, 32))
declare const aUnion: { x: number } | { y: string };
>aUnion : Symbol(aUnion, Decl(unknownType2.ts, 55, 13))
>x : Symbol(x, Decl(unknownType2.ts, 55, 23))
>y : Symbol(y, Decl(unknownType2.ts, 55, 39))
declare const anIntersection: { x: number } & { y: string };
>anIntersection : Symbol(anIntersection, Decl(unknownType2.ts, 56, 13))
>x : Symbol(x, Decl(unknownType2.ts, 56, 31))
>y : Symbol(y, Decl(unknownType2.ts, 56, 47))
declare const aFunction: () => number;
>aFunction : Symbol(aFunction, Decl(unknownType2.ts, 57, 13))
if (u === aString) {
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
>aString : Symbol(aString, Decl(unknownType2.ts, 50, 13))
let uString: string = u;
>uString : Symbol(uString, Decl(unknownType2.ts, 60, 7))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
}
if (u === aBoolean) {
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
>aBoolean : Symbol(aBoolean, Decl(unknownType2.ts, 51, 13))
let uString: boolean = u;
>uString : Symbol(uString, Decl(unknownType2.ts, 64, 7))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
}
if (u === aNumber) {
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
>aNumber : Symbol(aNumber, Decl(unknownType2.ts, 52, 13))
let uNumber: number = u;
>uNumber : Symbol(uNumber, Decl(unknownType2.ts, 68, 7))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
}
if (u === anObject) {
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
>anObject : Symbol(anObject, Decl(unknownType2.ts, 53, 13))
let uObject: object = u;
>uObject : Symbol(uObject, Decl(unknownType2.ts, 72, 7))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
}
if (u === anObjectLiteral) {
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
>anObjectLiteral : Symbol(anObjectLiteral, Decl(unknownType2.ts, 54, 13))
let uObjectLiteral: object = u;
>uObjectLiteral : Symbol(uObjectLiteral, Decl(unknownType2.ts, 76, 7))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
}
if (u === aUnion) {
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
>aUnion : Symbol(aUnion, Decl(unknownType2.ts, 55, 13))
type unionDoesNotNarrow = isTrue<isUnknown<typeof u>>
>unionDoesNotNarrow : Symbol(unionDoesNotNarrow, Decl(unknownType2.ts, 79, 19))
>isTrue : Symbol(isTrue, Decl(unknownType2.ts, 0, 53))
>isUnknown : Symbol(isUnknown, Decl(unknownType2.ts, 0, 0))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
}
if (u === anIntersection) {
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
>anIntersection : Symbol(anIntersection, Decl(unknownType2.ts, 56, 13))
type intersectionDoesNotNarrow = isTrue<isUnknown<typeof u>>
>intersectionDoesNotNarrow : Symbol(intersectionDoesNotNarrow, Decl(unknownType2.ts, 83, 27))
>isTrue : Symbol(isTrue, Decl(unknownType2.ts, 0, 53))
>isUnknown : Symbol(isUnknown, Decl(unknownType2.ts, 0, 0))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
}
if (u === aFunction) {
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
>aFunction : Symbol(aFunction, Decl(unknownType2.ts, 57, 13))
let uFunction: object = u;
>uFunction : Symbol(uFunction, Decl(unknownType2.ts, 88, 7))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
}
enum NumberEnum {
>NumberEnum : Symbol(NumberEnum, Decl(unknownType2.ts, 89, 1))
A,
>A : Symbol(NumberEnum.A, Decl(unknownType2.ts, 91, 17))
B,
>B : Symbol(NumberEnum.B, Decl(unknownType2.ts, 92, 6))
C
>C : Symbol(NumberEnum.C, Decl(unknownType2.ts, 93, 6))
}
enum StringEnum {
>StringEnum : Symbol(StringEnum, Decl(unknownType2.ts, 95, 1))
A = "A",
>A : Symbol(StringEnum.A, Decl(unknownType2.ts, 97, 17))
B = "B",
>B : Symbol(StringEnum.B, Decl(unknownType2.ts, 98, 12))
C = "C"
>C : Symbol(StringEnum.C, Decl(unknownType2.ts, 99, 12))
}
if (u === NumberEnum || u === StringEnum) {
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
>NumberEnum : Symbol(NumberEnum, Decl(unknownType2.ts, 89, 1))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
>StringEnum : Symbol(StringEnum, Decl(unknownType2.ts, 95, 1))
let enumObj: object = u;
>enumObj : Symbol(enumObj, Decl(unknownType2.ts, 104, 7))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
}
if(u === NumberEnum.A) {
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
>NumberEnum.A : Symbol(NumberEnum.A, Decl(unknownType2.ts, 91, 17))
>NumberEnum : Symbol(NumberEnum, Decl(unknownType2.ts, 89, 1))
>A : Symbol(NumberEnum.A, Decl(unknownType2.ts, 91, 17))
let a: NumberEnum.A = u
>a : Symbol(a, Decl(unknownType2.ts, 108, 7))
>NumberEnum : Symbol(NumberEnum, Decl(unknownType2.ts, 89, 1))
>A : Symbol(NumberEnum.A, Decl(unknownType2.ts, 91, 17))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
}
if(u === StringEnum.B) {
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
>StringEnum.B : Symbol(StringEnum.B, Decl(unknownType2.ts, 98, 12))
>StringEnum : Symbol(StringEnum, Decl(unknownType2.ts, 95, 1))
>B : Symbol(StringEnum.B, Decl(unknownType2.ts, 98, 12))
let b: StringEnum.B = u
>b : Symbol(b, Decl(unknownType2.ts, 112, 7))
>StringEnum : Symbol(StringEnum, Decl(unknownType2.ts, 95, 1))
>B : Symbol(StringEnum.B, Decl(unknownType2.ts, 98, 12))
>u : Symbol(u, Decl(unknownType2.ts, 6, 5))
}
+178 -1
View File
@@ -105,7 +105,6 @@ if (!(u === 42)) {
type A = isTrue<isUnknown<typeof u>>
>A : true
>u : unknown
}
if (u !== 42) {
@@ -148,3 +147,181 @@ if (u == Object) {
>u : unknown
}
declare const aString: string;
>aString : string
declare const aBoolean: boolean;
>aBoolean : boolean
declare const aNumber: number;
>aNumber : number
declare const anObject: object;
>anObject : object
declare const anObjectLiteral: { x: number };
>anObjectLiteral : { x: number; }
>x : number
declare const aUnion: { x: number } | { y: string };
>aUnion : { x: number; } | { y: string; }
>x : number
>y : string
declare const anIntersection: { x: number } & { y: string };
>anIntersection : { x: number; } & { y: string; }
>x : number
>y : string
declare const aFunction: () => number;
>aFunction : () => number
if (u === aString) {
>u === aString : boolean
>u : unknown
>aString : string
let uString: string = u;
>uString : string
>u : string
}
if (u === aBoolean) {
>u === aBoolean : boolean
>u : unknown
>aBoolean : boolean
let uString: boolean = u;
>uString : boolean
>u : boolean
}
if (u === aNumber) {
>u === aNumber : boolean
>u : unknown
>aNumber : number
let uNumber: number = u;
>uNumber : number
>u : number
}
if (u === anObject) {
>u === anObject : boolean
>u : unknown
>anObject : object
let uObject: object = u;
>uObject : object
>u : object
}
if (u === anObjectLiteral) {
>u === anObjectLiteral : boolean
>u : unknown
>anObjectLiteral : { x: number; }
let uObjectLiteral: object = u;
>uObjectLiteral : object
>u : object
}
if (u === aUnion) {
>u === aUnion : boolean
>u : unknown
>aUnion : { x: number; } | { y: string; }
type unionDoesNotNarrow = isTrue<isUnknown<typeof u>>
>unionDoesNotNarrow : true
>u : unknown
}
if (u === anIntersection) {
>u === anIntersection : boolean
>u : unknown
>anIntersection : { x: number; } & { y: string; }
type intersectionDoesNotNarrow = isTrue<isUnknown<typeof u>>
>intersectionDoesNotNarrow : true
>u : unknown
}
if (u === aFunction) {
>u === aFunction : boolean
>u : unknown
>aFunction : () => number
let uFunction: object = u;
>uFunction : object
>u : object
}
enum NumberEnum {
>NumberEnum : NumberEnum
A,
>A : NumberEnum.A
B,
>B : NumberEnum.B
C
>C : NumberEnum.C
}
enum StringEnum {
>StringEnum : StringEnum
A = "A",
>A : StringEnum.A
>"A" : "A"
B = "B",
>B : StringEnum.B
>"B" : "B"
C = "C"
>C : StringEnum.C
>"C" : "C"
}
if (u === NumberEnum || u === StringEnum) {
>u === NumberEnum || u === StringEnum : boolean
>u === NumberEnum : boolean
>u : unknown
>NumberEnum : typeof NumberEnum
>u === StringEnum : boolean
>u : unknown
>StringEnum : typeof StringEnum
let enumObj: object = u;
>enumObj : object
>u : object
}
if(u === NumberEnum.A) {
>u === NumberEnum.A : boolean
>u : unknown
>NumberEnum.A : NumberEnum.A
>NumberEnum : typeof NumberEnum
>A : NumberEnum.A
let a: NumberEnum.A = u
>a : NumberEnum.A
>NumberEnum : any
>u : NumberEnum.A
}
if(u === StringEnum.B) {
>u === StringEnum.B : boolean
>u : unknown
>StringEnum.B : StringEnum.B
>StringEnum : typeof StringEnum
>B : StringEnum.B
let b: StringEnum.B = u
>b : StringEnum.B
>StringEnum : any
>u : StringEnum.B
}
@@ -0,0 +1,23 @@
// @strictNullChecks: true
// Repro from #20873
let { } = null;
({} = null);
let { } = undefined;
({} = undefined);
let { } = Math.random() ? {} : null;
({} = Math.random() ? {} : null);
let { } = Math.random() ? {} : undefined;
({} = Math.random() ? {} : undefined);
let { } = Math.random() ? null : undefined;
({} = Math.random() ? null : undefined);
@@ -32,7 +32,6 @@ if (u === symb) {
if (!(u === 42)) {
type A = isTrue<isUnknown<typeof u>>
}
if (u !== 42) {
@@ -50,3 +49,68 @@ if (u == true) {
if (u == Object) {
type E = isTrue<isUnknown<typeof u>>
}
declare const aString: string;
declare const aBoolean: boolean;
declare const aNumber: number;
declare const anObject: object;
declare const anObjectLiteral: { x: number };
declare const aUnion: { x: number } | { y: string };
declare const anIntersection: { x: number } & { y: string };
declare const aFunction: () => number;
if (u === aString) {
let uString: string = u;
}
if (u === aBoolean) {
let uString: boolean = u;
}
if (u === aNumber) {
let uNumber: number = u;
}
if (u === anObject) {
let uObject: object = u;
}
if (u === anObjectLiteral) {
let uObjectLiteral: object = u;
}
if (u === aUnion) {
type unionDoesNotNarrow = isTrue<isUnknown<typeof u>>
}
if (u === anIntersection) {
type intersectionDoesNotNarrow = isTrue<isUnknown<typeof u>>
}
if (u === aFunction) {
let uFunction: object = u;
}
enum NumberEnum {
A,
B,
C
}
enum StringEnum {
A = "A",
B = "B",
C = "C"
}
if (u === NumberEnum || u === StringEnum) {
let enumObj: object = u;
}
if(u === NumberEnum.A) {
let a: NumberEnum.A = u
}
if(u === StringEnum.B) {
let b: StringEnum.B = u
}