Skip to content

Commit adb37a5

Browse files
committed
Optimize and remove more redundant elaborations
1 parent 2670b26 commit adb37a5

File tree

2 files changed

+13
-18
lines changed

2 files changed

+13
-18
lines changed

src/compiler/checker.ts

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18292,22 +18292,17 @@ namespace ts {
1829218292
return Ternary.True;
1829318293
}
1829418294

18295-
// Try to see if we're relating something like `Foo` -> `Bar | null | undefined`.
18296-
// If so, reporting the `null` and `undefined` in the type is hardly useful.
18297-
// First, see if we're even relating an object type to a union.
18298-
// Then see if the target is stripped down to a single non-union type.
18299-
// Note
18300-
// * We actually want to remove null and undefined naively here (rather than using getNonNullableType),
18301-
// since we don't want to end up with a worse error like "`Foo` is not assignable to `NonNullable<T>`"
18302-
// when dealing with generics.
18303-
// * We also don't deal with primitive source types, since we already halt elaboration below.
18304-
if (target.flags & TypeFlags.Union && source.flags & TypeFlags.Object &&
18305-
(target as UnionType).types.length <= 3 && maybeTypeOfKind(target, TypeFlags.Nullable)) {
18306-
const nullStrippedTarget = extractTypesOfKind(target, ~TypeFlags.Nullable);
18307-
if (!(nullStrippedTarget.flags & (TypeFlags.Union | TypeFlags.Never))) {
18308-
target = getNormalizedType(nullStrippedTarget, /*writing*/ true);
18309-
}
18310-
if (source === nullStrippedTarget) return Ternary.True;
18295+
// See if we're relating a definitely non-nullable type to a union that includes null and/or undefined
18296+
// plus a single non-nullable type. If so, remove null and/or undefined from the target type.
18297+
if (source.flags & TypeFlags.DefinitelyNonNullable && target.flags & TypeFlags.Union) {
18298+
const types = (target as UnionType).types;
18299+
const candidate = types.length === 2 && types[0].flags & TypeFlags.Nullable ? types[1] :
18300+
types.length === 3 && types[0].flags & TypeFlags.Nullable && types[1].flags & TypeFlags.Nullable ? types[2] :
18301+
undefined;
18302+
if (candidate && !(candidate.flags & TypeFlags.Nullable)) {
18303+
target = getNormalizedType(candidate, /*writing*/ true);
18304+
if (source === target) return Ternary.True;
18305+
}
1831118306
}
1831218307

1831318308
if (relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) ||
@@ -18949,8 +18944,6 @@ namespace ts {
1894918944
return result;
1895018945
}
1895118946
if (source.flags & TypeFlags.Intersection || source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.Union) {
18952-
// (T extends 1 | 2) & 1 <=> 1
18953-
// (T extends 1 | 2) <=> T & 1 | T & 2
1895418947
// The combined constraint of an intersection type is the intersection of the constraints of
1895518948
// the constituents. When an intersection type contains instantiable types with union type
1895618949
// constraints, there are situations where we need to examine the combined constraint. One is

src/compiler/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5174,6 +5174,8 @@ namespace ts {
51745174
ESSymbolLike = ESSymbol | UniqueESSymbol,
51755175
VoidLike = Void | Undefined,
51765176
/* @internal */
5177+
DefinitelyNonNullable = StringLike | NumberLike | BigIntLike | BooleanLike | EnumLike | ESSymbolLike | Object | NonPrimitive,
5178+
/* @internal */
51775179
DisjointDomains = NonPrimitive | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbolLike | VoidLike | Null,
51785180
UnionOrIntersection = Union | Intersection,
51795181
StructuredType = Object | Union | Intersection,

0 commit comments

Comments
 (0)