Skip to content

Commit 483afea

Browse files
committed
Less aggressive subtype reduction in union types
1 parent 5c661ba commit 483afea

File tree

1 file changed

+37
-11
lines changed

1 file changed

+37
-11
lines changed

Diff for: src/compiler/checker.ts

+37-11
Original file line numberDiff line numberDiff line change
@@ -2066,7 +2066,7 @@ module ts {
20662066
}
20672067

20682068
function resolveTupleTypeMembers(type: TupleType) {
2069-
var arrayType = resolveObjectTypeMembers(createArrayType(getBestCommonType(type.elementTypes)));
2069+
var arrayType = resolveObjectTypeMembers(createArrayType(getUnionType(type.elementTypes)));
20702070
var members = createTupleTypeMemberSymbols(type.elementTypes);
20712071
addInheritedMembers(members, arrayType.properties);
20722072
setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType);
@@ -2716,13 +2716,41 @@ module ts {
27162716
}
27172717
}
27182718

2719-
function getUnionType(types: Type[]): Type {
2719+
function containsAnyType(types: Type[]) {
2720+
for (var i = 0; i < types.length; i++) {
2721+
if (types[i].flags & TypeFlags.Any) {
2722+
return true;
2723+
}
2724+
}
2725+
return false;
2726+
}
2727+
2728+
function removeAllButLast(types: Type[], typeToRemove: Type) {
2729+
var i = types.length;
2730+
while (i > 0 && types.length > 1) {
2731+
i--;
2732+
if (types[i] === typeToRemove) {
2733+
types.splice(i, 1);
2734+
}
2735+
}
2736+
}
2737+
2738+
function getUnionType(types: Type[], noSubtypeReduction?: boolean): Type {
27202739
if (types.length === 0) {
27212740
return emptyObjectType;
27222741
}
27232742
var sortedTypes: Type[] = [];
27242743
addTypesToSortedSet(sortedTypes, types);
2725-
removeSubtypes(sortedTypes);
2744+
if (noSubtypeReduction) {
2745+
if (containsAnyType(sortedTypes)) {
2746+
return anyType;
2747+
}
2748+
removeAllButLast(sortedTypes, undefinedType);
2749+
removeAllButLast(sortedTypes, nullType);
2750+
}
2751+
else {
2752+
removeSubtypes(sortedTypes);
2753+
}
27262754
if (sortedTypes.length === 1) {
27272755
return sortedTypes[0];
27282756
}
@@ -2738,7 +2766,7 @@ module ts {
27382766
function getTypeFromUnionTypeNode(node: UnionTypeNode): Type {
27392767
var links = getNodeLinks(node);
27402768
if (!links.resolvedType) {
2741-
links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode));
2769+
links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode), /*noSubtypeReduction*/ true);
27422770
}
27432771
return links.resolvedType;
27442772
}
@@ -2956,7 +2984,7 @@ module ts {
29562984
return createTupleType(instantiateList((<TupleType>type).elementTypes, mapper, instantiateType));
29572985
}
29582986
if (type.flags & TypeFlags.Union) {
2959-
return getUnionType(instantiateList((<UnionType>type).types, mapper, instantiateType));
2987+
return getUnionType(instantiateList((<UnionType>type).types, mapper, instantiateType), /*noSubtypeReduction*/ true);
29602988
}
29612989
}
29622990
return type;
@@ -3606,7 +3634,7 @@ module ts {
36063634
return forEach(types, t => isSupertypeOfEach(t, types) ? t : undefined);
36073635
}
36083636

3609-
function getBestCommonType(types: Type[], contextualType?: Type): Type {
3637+
function getBestCommonType(types: Type[], contextualType: Type): Type {
36103638
return contextualType && isSupertypeOfEach(contextualType, types) ? contextualType : getUnionType(types); }
36113639

36123640
function isTypeOfObjectLiteral(type: Type): boolean {
@@ -4558,7 +4586,7 @@ module ts {
45584586
return createTupleType(elementTypes);
45594587
}
45604588
var contextualElementType = contextualType && !isInferentialContext(contextualMapper) ? getIndexTypeOfType(contextualType, IndexKind.Number) : undefined;
4561-
var elementType = elements.length || contextualElementType ? getBestCommonType(deduplicate(elementTypes), contextualElementType) : undefinedType;
4589+
var elementType = elements.length || contextualElementType ? getBestCommonType(elementTypes, contextualElementType) : undefinedType;
45624590
return createArrayType(elementType);
45634591
}
45644592

@@ -5601,7 +5629,7 @@ module ts {
56015629
case SyntaxKind.AmpersandAmpersandToken:
56025630
return rightType;
56035631
case SyntaxKind.BarBarToken:
5604-
return getBestCommonType([leftType, rightType], isInferentialContext(contextualMapper) ? undefined : getContextualType(node));
5632+
return getUnionType([leftType, rightType]);
56055633
case SyntaxKind.EqualsToken:
56065634
checkAssignmentOperator(rightType);
56075635
return rightType;
@@ -5651,9 +5679,7 @@ module ts {
56515679
checkExpression(node.condition);
56525680
var type1 = checkExpression(node.whenTrue, contextualMapper);
56535681
var type2 = checkExpression(node.whenFalse, contextualMapper);
5654-
var contextualType = isInferentialContext(contextualMapper) ? undefined : getContextualType(node);
5655-
var resultType = getBestCommonType([type1, type2], contextualType);
5656-
return resultType;
5682+
return getUnionType([type1, type2]);
56575683
}
56585684

56595685
function checkExpressionWithContextualType(node: Expression, contextualType: Type, contextualMapper?: TypeMapper): Type {

0 commit comments

Comments
 (0)