Skip to content

Commit 9e8f24b

Browse files
committed
Create maps for mixed unions, but not for small or primitive only unions
1 parent 216266b commit 9e8f24b

File tree

2 files changed

+35
-32
lines changed

2 files changed

+35
-32
lines changed

src/compiler/checker.ts

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17533,13 +17533,11 @@ namespace ts {
1753317533
if (containsType(targetTypes, source)) {
1753417534
return Ternary.True;
1753517535
}
17536-
if (targetTypes.length >= 4) {
17537-
const match = getMatchingUnionConstituentForType(<UnionType>target, source);
17538-
if (match) {
17539-
const related = isRelatedTo(source, match, /*reportErrors*/ false);
17540-
if (related) {
17541-
return related;
17542-
}
17536+
const match = getMatchingUnionConstituentForType(<UnionType>target, source);
17537+
if (match) {
17538+
const related = isRelatedTo(source, match, /*reportErrors*/ false);
17539+
if (related) {
17540+
return related;
1754317541
}
1754417542
}
1754517543
}
@@ -21378,21 +21376,32 @@ namespace ts {
2137821376
return result;
2137921377
}
2138021378

21381-
function getUnitTypeProperties(unionType: UnionType): Symbol[] {
21382-
return unionType.unitTypeProperties || (unionType.unitTypeProperties =
21383-
filter(getPropertiesOfUnionOrIntersectionType(unionType), prop => !!(
21384-
getCheckFlags(prop) & CheckFlags.SyntheticProperty &&
21385-
((<TransientSymbol>prop).checkFlags & CheckFlags.UnitDiscriminant) === CheckFlags.UnitDiscriminant)));
21379+
function getKeyPropertyNames(unionType: UnionType): __String[] | undefined {
21380+
const types = unionType.types;
21381+
if (types.length < 10 || getObjectFlags(unionType) & ObjectFlags.PrimitiveUnion) {
21382+
return undefined;
21383+
}
21384+
let keyPropertyNames = unionType.keyPropertyNames;
21385+
if (!keyPropertyNames) {
21386+
keyPropertyNames = unionType.keyPropertyNames = [];
21387+
const propType = find(types, t => !!(t.flags & (TypeFlags.Object | TypeFlags.Intersection)) && getPropertiesOfType(t).length !== 0) || unknownType;
21388+
for (const name of map(getPropertiesOfType(propType), prop => prop.escapedName)) {
21389+
if (every(types, t => !(t.flags & (TypeFlags.Object | TypeFlags.Intersection)) || isUnitType(getTypeOfPropertyOfType(t, name) || unknownType))) {
21390+
keyPropertyNames.push(name);
21391+
}
21392+
}
21393+
}
21394+
return keyPropertyNames.length ? keyPropertyNames : undefined;
2138621395
}
2138721396

2138821397
function getUnionConstituentKeyForType(unionType: UnionType, type: Type) {
21389-
const unitTypeProperties = getUnitTypeProperties(unionType);
21390-
if (unitTypeProperties.length === 0) {
21398+
const keyPropertyNames = getKeyPropertyNames(unionType);
21399+
if (!keyPropertyNames) {
2139121400
return undefined;
2139221401
}
2139321402
const propTypes = [];
21394-
for (const prop of unitTypeProperties) {
21395-
const propType = getTypeOfPropertyOfType(type, prop.escapedName);
21403+
for (const name of keyPropertyNames) {
21404+
const propType = getTypeOfPropertyOfType(type, name);
2139621405
if (!(propType && isUnitType(propType))) {
2139721406
return undefined;
2139821407
}
@@ -21402,14 +21411,14 @@ namespace ts {
2140221411
}
2140321412

2140421413
function getUnionConstituentKeyForObjectLiteral(unionType: UnionType, node: ObjectLiteralExpression) {
21405-
const unitTypeProperties = getUnitTypeProperties(unionType);
21406-
if (unitTypeProperties.length === 0) {
21414+
const keyPropertyNames = getKeyPropertyNames(unionType);
21415+
if (!keyPropertyNames) {
2140721416
return undefined;
2140821417
}
2140921418
const propTypes = [];
21410-
for (const prop of unitTypeProperties) {
21419+
for (const name of keyPropertyNames) {
2141121420
const propNode = find(node.properties, p => p.symbol && p.kind === SyntaxKind.PropertyAssignment &&
21412-
p.symbol.escapedName === prop.escapedName && isPossiblyDiscriminantValue(p.initializer));
21421+
p.symbol.escapedName === name && isPossiblyDiscriminantValue(p.initializer));
2141321422
const propType = propNode && getTypeOfExpression((<PropertyAssignment>propNode).initializer);
2141421423
if (!(propType && isUnitType(propType))) {
2141521424
return undefined;
@@ -24717,16 +24726,10 @@ namespace ts {
2471724726
getContextualType(node, contextFlags);
2471824727
const instantiatedType = instantiateContextualType(contextualType, node, contextFlags);
2471924728
if (instantiatedType && !(contextFlags && contextFlags & ContextFlags.NoConstraints && instantiatedType.flags & TypeFlags.TypeVariable)) {
24720-
const apparentType = mapType(instantiatedType, getApparentType, /*noReductions*/ true);
24721-
if (apparentType.flags & TypeFlags.Union) {
24722-
if (isObjectLiteralExpression(node)) {
24723-
return discriminateContextualTypeByObjectMembers(node, apparentType as UnionType);
24724-
}
24725-
else if (isJsxAttributes(node)) {
24726-
return discriminateContextualTypeByJSXAttributes(node, apparentType as UnionType);
24727-
}
24728-
}
24729-
return apparentType;
24729+
const discriminatedType = instantiatedType.flags & TypeFlags.Union && isObjectLiteralExpression(node) ? discriminateContextualTypeByObjectMembers(node, instantiatedType as UnionType) :
24730+
instantiatedType.flags & TypeFlags.Union && isJsxAttributes(node) ? discriminateContextualTypeByJSXAttributes(node, instantiatedType as UnionType) :
24731+
instantiatedType;
24732+
return mapType(discriminatedType, getApparentType, /*noReductions*/ true);
2473024733
}
2473124734
}
2473224735

src/compiler/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5306,9 +5306,9 @@ namespace ts {
53065306
/* @internal */
53075307
origin?: Type; // Denormalized union, intersection, or index type in which union originates
53085308
/* @internal */
5309-
unitTypeProperties?: Symbol[] | undefined;
5309+
keyPropertyNames?: __String[] | undefined; // Unit type properties that exist in every object/intersection in union type
53105310
/* @internal */
5311-
constituentMap?: Map<Type | undefined>;
5311+
constituentMap?: ESMap<string, Type | undefined>; // Constituents keyed by unit type discriminants
53125312
}
53135313

53145314
export interface IntersectionType extends UnionOrIntersectionType {

0 commit comments

Comments
 (0)