From 35e9e165b17af24b00ecc1f397253d371333cb71 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 27 Jun 2018 23:25:26 -0700 Subject: [PATCH] Strip `null` and `undefined` from targets when relating from certain atomic types. --- src/compiler/checker.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index eb23835ffc4..fce41c663a1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10631,6 +10631,22 @@ namespace ts { target = getSimplifiedType(target); } + // Try to see if we're relating something like `Foo` -> `Bar | null | undefined`. + // If so, reporting the `null` and `undefined` in the type is hardly useful. + // First, see if we're even relating an atomic type to a union. + // Then see if the target is stripped down to a single non-union type. + // We actually want to remove null and undefined naively here (rather than getNonNullableType), + // since we don't want to end up with a worse error like "`Foo` is not assignable to `NonNullable`" + // when dealing with generics. + if (target.flags & TypeFlags.Union && + source.flags & ((TypeFlags.Primitive | TypeFlags.Object) & ~(TypeFlags.Nullable | TypeFlags.Void)) && + (target as UnionType).types.length <= 3 && maybeTypeOfKind(target, TypeFlags.Nullable)) { + const nullStrippedTarget = extractTypesOfKind(target, ~TypeFlags.Nullable); + if (!(nullStrippedTarget.flags & (TypeFlags.Union | TypeFlags.Never))) { + target = nullStrippedTarget; + } + } + // both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases if (source === target) return Ternary.True; @@ -12223,7 +12239,7 @@ namespace ts { if (deferredGlobalNonNullableTypeAlias !== unknownSymbol) { return getTypeAliasInstantiation(deferredGlobalNonNullableTypeAlias, [type]); } - return getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull); // Type alias unavailable, fall back to non-higherorder behavior + return getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull); // Type alias unavailable, fall back to non-higher-order behavior } function getNonNullableType(type: Type): Type {