diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cd0758fe5c3..2bc0893899b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -122,7 +122,7 @@ namespace ts { const unknownType = createIntrinsicType(TypeFlags.Any, "unknown"); const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - const emptyUnionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); + const nothingType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); const emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); emptyGenericType.instantiations = {}; @@ -2030,7 +2030,7 @@ namespace ts { writeUnionOrIntersectionType(type, flags); } else if (type.flags & TypeFlags.Anonymous) { - if (type === emptyUnionType) { + if (type === nothingType) { writer.writeKeyword("nothing"); } else { @@ -5006,7 +5006,7 @@ namespace ts { if (type.flags & TypeFlags.Undefined) typeSet.containsUndefined = true; if (type.flags & TypeFlags.Null) typeSet.containsNull = true; } - else if (type !== emptyUnionType && !contains(typeSet, type)) { + else if (type !== nothingType && !contains(typeSet, type)) { typeSet.push(type); } } @@ -5047,7 +5047,10 @@ namespace ts { // a named type that circularly references itself. function getUnionType(types: Type[], noSubtypeReduction?: boolean): Type { if (types.length === 0) { - return emptyUnionType; + return nothingType; + } + if (types.length === 1) { + return types[0]; } const typeSet = [] as TypeSet; addTypesToSet(typeSet, types, TypeFlags.Union); @@ -5064,7 +5067,7 @@ namespace ts { if (typeSet.length === 0) { return typeSet.containsNull ? nullType : typeSet.containsUndefined ? undefinedType : - emptyUnionType; + nothingType; } else if (typeSet.length === 1) { return typeSet[0]; @@ -7483,7 +7486,7 @@ namespace ts { function getTypeWithFacts(type: Type, include: TypeFacts) { if (!(type.flags & TypeFlags.Union)) { - return getTypeFacts(type) & include ? type : emptyUnionType; + return getTypeFacts(type) & include ? type : nothingType; } let firstType: Type; let types: Type[]; @@ -7500,7 +7503,7 @@ namespace ts { } } } - return firstType ? types ? getUnionType(types, /*noSubtypeReduction*/ true) : firstType : emptyUnionType; + return firstType ? types ? getUnionType(types, /*noSubtypeReduction*/ true) : firstType : nothingType; } function getTypeWithDefault(type: Type, defaultExpression: Expression) { @@ -7703,7 +7706,7 @@ namespace ts { function getTypeAtFlowCondition(flow: FlowCondition) { let type = getTypeAtFlowNode(flow.antecedent); - if (type !== emptyUnionType) { + if (type !== nothingType) { // If we have an antecedent type (meaning we're reachable in some way), we first // attempt to narrow the antecedent type. If that produces the nothing type, then // we take the type guard as an indication that control could reach here in a @@ -7713,7 +7716,7 @@ namespace ts { // narrow that. const assumeTrue = (flow.flags & FlowFlags.TrueCondition) !== 0; type = narrowType(type, flow.expression, assumeTrue); - if (type === emptyUnionType) { + if (type === nothingType) { type = narrowType(declaredType, flow.expression, assumeTrue); } } @@ -7735,7 +7738,7 @@ namespace ts { antecedentTypes.push(type); } } - return antecedentTypes.length === 1 ? antecedentTypes[0] : getUnionType(antecedentTypes); + return getUnionType(antecedentTypes); } function getTypeAtFlowLoopLabel(flow: FlowLabel) { @@ -7785,7 +7788,7 @@ namespace ts { antecedentTypes.push(type); } } - return cache[key] = antecedentTypes.length === 1 ? antecedentTypes[0] : getUnionType(antecedentTypes); + return cache[key] = getUnionType(antecedentTypes); } function narrowTypeByTruthiness(type: Type, expr: Expression, assumeTrue: boolean): Type { @@ -7936,7 +7939,7 @@ namespace ts { const targetType = type.flags & TypeFlags.TypeParameter ? getApparentType(type) : type; return isTypeAssignableTo(candidate, targetType) ? candidate : isTypeAssignableTo(type, candidate) ? type : - emptyUnionType; + nothingType; } function narrowTypeByTypePredicate(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type { @@ -14741,7 +14744,7 @@ namespace ts { arrayType = getUnionType(filter((arrayOrStringType as UnionType).types, t => !(t.flags & TypeFlags.StringLike))); } else if (arrayOrStringType.flags & TypeFlags.StringLike) { - arrayType = emptyUnionType; + arrayType = nothingType; } const hasStringConstituent = arrayOrStringType !== arrayType; let reportedError = false; @@ -14753,7 +14756,7 @@ namespace ts { // Now that we've removed all the StringLike types, if no constituents remain, then the entire // arrayOrStringType was a string. - if (arrayType === emptyUnionType) { + if (arrayType === nothingType) { return stringType; } }