Improved handing of union types in type guards
This commit is contained in:
parent
bf46e50f89
commit
59e266de02
|
@ -4709,13 +4709,21 @@ module ts {
|
||||||
if (!isTypeSubtypeOf(rightType, globalFunctionType)) {
|
if (!isTypeSubtypeOf(rightType, globalFunctionType)) {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
// Target type is type of prototype property
|
||||||
var prototypeProperty = getPropertyOfType(rightType, "prototype");
|
var prototypeProperty = getPropertyOfType(rightType, "prototype");
|
||||||
if (!prototypeProperty) {
|
if (!prototypeProperty) {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
var prototypeType = getTypeOfSymbol(prototypeProperty);
|
var targetType = getTypeOfSymbol(prototypeProperty);
|
||||||
// Narrow to type of prototype property if it is a subtype of current type
|
// Narrow to target type if it is a subtype of current type
|
||||||
return isTypeSubtypeOf(prototypeType, type) ? prototypeType : type;
|
if (isTypeSubtypeOf(targetType, type)) {
|
||||||
|
return targetType;
|
||||||
|
}
|
||||||
|
// If current type is a union type, remove all constituents that aren't subtypes of target type
|
||||||
|
if (type.flags && TypeFlags.Union) {
|
||||||
|
return getUnionType(filter((<UnionType>type).types, t => isTypeSubtypeOf(t, targetType)));
|
||||||
|
}
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Narrow the given type based on the given expression having the assumed boolean value
|
// Narrow the given type based on the given expression having the assumed boolean value
|
||||||
|
|
23
tests/baselines/reference/TypeGuardWithArrayUnion.js
Normal file
23
tests/baselines/reference/TypeGuardWithArrayUnion.js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
//// [TypeGuardWithArrayUnion.ts]
|
||||||
|
class Message {
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function saySize(message: Message | Message[]) {
|
||||||
|
if (message instanceof Array) {
|
||||||
|
return message.length; // Should have type Message[] here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//// [TypeGuardWithArrayUnion.js]
|
||||||
|
var Message = (function () {
|
||||||
|
function Message() {
|
||||||
|
}
|
||||||
|
return Message;
|
||||||
|
})();
|
||||||
|
function saySize(message) {
|
||||||
|
if (message instanceof Array) {
|
||||||
|
return message.length; // Should have type Message[] here
|
||||||
|
}
|
||||||
|
}
|
26
tests/baselines/reference/TypeGuardWithArrayUnion.types
Normal file
26
tests/baselines/reference/TypeGuardWithArrayUnion.types
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
=== tests/cases/conformance/expressions/typeGuards/TypeGuardWithArrayUnion.ts ===
|
||||||
|
class Message {
|
||||||
|
>Message : Message
|
||||||
|
|
||||||
|
value: string;
|
||||||
|
>value : string
|
||||||
|
}
|
||||||
|
|
||||||
|
function saySize(message: Message | Message[]) {
|
||||||
|
>saySize : (message: Message | Message[]) => number
|
||||||
|
>message : Message | Message[]
|
||||||
|
>Message : Message
|
||||||
|
>Message : Message
|
||||||
|
|
||||||
|
if (message instanceof Array) {
|
||||||
|
>message instanceof Array : boolean
|
||||||
|
>message : Message | Message[]
|
||||||
|
>Array : ArrayConstructor
|
||||||
|
|
||||||
|
return message.length; // Should have type Message[] here
|
||||||
|
>message.length : number
|
||||||
|
>message : Message[]
|
||||||
|
>length : number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -124,9 +124,9 @@ var r2: D1 | C2 = c2Ord1 instanceof C1 && c2Ord1; // C2 | D1
|
||||||
>r2 : C2 | D1
|
>r2 : C2 | D1
|
||||||
>D1 : D1
|
>D1 : D1
|
||||||
>C2 : C2
|
>C2 : C2
|
||||||
>c2Ord1 instanceof C1 && c2Ord1 : C2 | D1
|
>c2Ord1 instanceof C1 && c2Ord1 : D1
|
||||||
>c2Ord1 instanceof C1 : boolean
|
>c2Ord1 instanceof C1 : boolean
|
||||||
>c2Ord1 : C2 | D1
|
>c2Ord1 : C2 | D1
|
||||||
>C1 : typeof C1
|
>C1 : typeof C1
|
||||||
>c2Ord1 : C2 | D1
|
>c2Ord1 : D1
|
||||||
|
|
||||||
|
|
|
@ -154,9 +154,9 @@ var r2: D1 | C2 = c2Ord1 instanceof c1 && c2Ord1; // C2 | D1
|
||||||
>r2 : C2 | D1
|
>r2 : C2 | D1
|
||||||
>D1 : D1
|
>D1 : D1
|
||||||
>C2 : C2
|
>C2 : C2
|
||||||
>c2Ord1 instanceof c1 && c2Ord1 : C2 | D1
|
>c2Ord1 instanceof c1 && c2Ord1 : D1
|
||||||
>c2Ord1 instanceof c1 : boolean
|
>c2Ord1 instanceof c1 : boolean
|
||||||
>c2Ord1 : C2 | D1
|
>c2Ord1 : C2 | D1
|
||||||
>c1 : C1
|
>c1 : C1
|
||||||
>c2Ord1 : C2 | D1
|
>c2Ord1 : D1
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
class Message {
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function saySize(message: Message | Message[]) {
|
||||||
|
if (message instanceof Array) {
|
||||||
|
return message.length; // Should have type Message[] here
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue