From c110f57deb0c423c4e160ab5bce74c35187cb039 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 10 Oct 2018 15:11:35 -0700 Subject: [PATCH] Discriminant must include at least one unit type and no instantiable types --- src/compiler/checker.ts | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9578f7a106b..795b893f69e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12919,10 +12919,6 @@ namespace ts { isUnitType(type); } - function maybeUnitType(type: Type): boolean { - return type.flags & TypeFlags.Union ? some((type).types, isUnitType) : isUnitType(type); - } - function getBaseTypeOfLiteralType(type: Type): Type { return type.flags & TypeFlags.EnumLiteral ? getBaseTypeOfEnumLiteralType(type) : type.flags & TypeFlags.StringLiteral ? stringType : @@ -14216,12 +14212,26 @@ namespace ts { return undefined; } + function isDiscriminantType(type: Type): boolean { + if (type.flags & TypeFlags.Union) { + if (type.flags & (TypeFlags.Boolean | TypeFlags.EnumLiteral)) { + return true; + } + let combined = 0; + for (const t of (type).types) combined |= t.flags; + if (combined & TypeFlags.Unit && !(combined & TypeFlags.Instantiable)) { + return true; + } + } + return false; + } + function isDiscriminantProperty(type: Type | undefined, name: __String) { if (type && type.flags & TypeFlags.Union) { const prop = getUnionOrIntersectionProperty(type, name); if (prop && getCheckFlags(prop) & CheckFlags.SyntheticProperty) { if ((prop).isDiscriminantProperty === undefined) { - (prop).isDiscriminantProperty = !!((prop).checkFlags & CheckFlags.HasNonUniformType) && maybeUnitType(getTypeOfSymbol(prop)); + (prop).isDiscriminantProperty = !!((prop).checkFlags & CheckFlags.HasNonUniformType) && isDiscriminantType(getTypeOfSymbol(prop)); } return !!(prop).isDiscriminantProperty; }