Skip to content

Commit 3bf9f8e

Browse files
committed
Properly handle null and undefined in getCommonSupertype
1 parent 7b76416 commit 3bf9f8e

File tree

1 file changed

+20
-24
lines changed

1 file changed

+20
-24
lines changed

src/compiler/checker.ts

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21198,39 +21198,35 @@ namespace ts {
2119821198
function literalTypesWithSameBaseType(types: Type[]): boolean {
2119921199
let commonBaseType: Type | undefined;
2120021200
for (const t of types) {
21201-
const baseType = getBaseTypeOfLiteralType(t);
21202-
if (!commonBaseType) {
21203-
commonBaseType = baseType;
21204-
}
21205-
if (baseType === t || baseType !== commonBaseType) {
21206-
return false;
21201+
if (!(t.flags & TypeFlags.Never)) {
21202+
const baseType = getBaseTypeOfLiteralType(t);
21203+
commonBaseType ??= baseType;
21204+
if (baseType === t || baseType !== commonBaseType) {
21205+
return false;
21206+
}
2120721207
}
2120821208
}
2120921209
return true;
2121021210
}
2121121211

21212-
// When the candidate types are all literal types with the same base type, return a union
21213-
// of those literal types. Otherwise, return the leftmost type for which no type to the
21214-
// right is a supertype.
21215-
function getSupertypeOrUnion(types: Type[]): Type {
21216-
if (types.length === 1) {
21217-
return types[0];
21218-
}
21219-
return literalTypesWithSameBaseType(types) ?
21220-
getUnionType(types) :
21221-
reduceLeft(types, (s, t) => isTypeSubtypeOf(s, t) ? t : s)!;
21212+
function getCombinedTypeFlags(types: Type[]): TypeFlags {
21213+
return reduceLeft(types, (flags, t) => flags | (t.flags & TypeFlags.Union ? getCombinedTypeFlags((t as UnionType).types) : t.flags), 0);
2122221214
}
2122321215

2122421216
function getCommonSupertype(types: Type[]): Type {
21225-
if (!strictNullChecks) {
21226-
return getSupertypeOrUnion(types);
21227-
}
21228-
const primaryTypes = filter(types, t => !(t.flags & TypeFlags.Nullable));
21229-
if (primaryTypes.length) {
21230-
const supertypeOrUnion = getSupertypeOrUnion(primaryTypes);
21231-
return primaryTypes === types ? supertypeOrUnion : getUnionType([supertypeOrUnion, ...filter(types, t => !!(t.flags & TypeFlags.Nullable))]);
21217+
if (types.length === 1) {
21218+
return types[0];
2123221219
}
21233-
return getUnionType(types, UnionReduction.Subtype);
21220+
// Remove nullable types from each of the candidates.
21221+
const primaryTypes = strictNullChecks ? sameMap(types, t => filterType(t, u => !(u.flags & TypeFlags.Nullable))) : types;
21222+
// When the candidate types are all literal types with the same base type, return a union
21223+
// of those literal types. Otherwise, return the leftmost type for which no type to the
21224+
// right is a supertype.
21225+
const superTypeOrUnion = literalTypesWithSameBaseType(primaryTypes) ?
21226+
getUnionType(primaryTypes) :
21227+
reduceLeft(primaryTypes, (s, t) => isTypeSubtypeOf(s, t) ? t : s)!;
21228+
// Add any nullable types that occurred in the candidates back to the result.
21229+
return primaryTypes === types ? superTypeOrUnion : getNullableType(superTypeOrUnion, getCombinedTypeFlags(types) & TypeFlags.Nullable);
2123421230
}
2123521231

2123621232
// Return the leftmost type for which no type to the right is a subtype.

0 commit comments

Comments
 (0)