Make special intersections order-independent (#52782)

This commit is contained in:
Mateusz Burzyński
2023-03-08 00:39:14 +01:00
committed by GitHub
parent 3f4d16a25e
commit 88adf8014b
8 changed files with 25 additions and 9 deletions

View File

@@ -16766,12 +16766,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return reduceLeft(types, (n, t) => n + getConstituentCount(t), 0);
}
function areIntersectedTypesAvoidingPrimitiveReduction(t1: Type, t2: Type) {
return !!(t1.flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) && t2 === emptyTypeLiteralType;
}
function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
const aliasSymbol = getAliasSymbolForTypeNode(node);
const types = map(node.types, getTypeFromTypeNode);
const noSupertypeReduction = types.length === 2 && !!(types[0].flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) && types[1] === emptyTypeLiteralType;
const noSupertypeReduction = types.length === 2 && (areIntersectedTypesAvoidingPrimitiveReduction(types[0], types[1]) || areIntersectedTypesAvoidingPrimitiveReduction(types[1], types[0]));
links.resolvedType = getIntersectionType(types, aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol), noSupertypeReduction);
}
return links.resolvedType;

View File

@@ -2165,6 +2165,10 @@ export function isStringOrRegularExpressionOrTemplateLiteral(kind: SyntaxKind):
return false;
}
function areIntersectedTypesAvoidingStringReduction(checker: TypeChecker, t1: Type, t2: Type) {
return !!(t1.flags & TypeFlags.String) && checker.isEmptyAnonymousObjectType(t2);
}
/** @internal */
export function isStringAndEmptyAnonymousObjectIntersection(type: Type) {
if (!type.isIntersection()) {
@@ -2172,8 +2176,8 @@ export function isStringAndEmptyAnonymousObjectIntersection(type: Type) {
}
const { types, checker } = type;
return types.length === 2
&& (types[0].flags & TypeFlags.String) && checker.isEmptyAnonymousObjectType(types[1]);
return types.length === 2 &&
(areIntersectedTypesAvoidingStringReduction(checker, types[0], types[1]) || areIntersectedTypesAvoidingStringReduction(checker, types[1], types[0]));
}
/** @internal */