Merge pull request #25287 from Microsoft/skipToNonNullTargets

Skip to non null targets in error messages
This commit is contained in:
Daniel Rosenwasser 2018-06-28 22:26:36 -07:00 committed by GitHub
commit f23c180a38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 119 additions and 11 deletions

View File

@ -10631,6 +10631,23 @@ 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 object type to a union.
// Then see if the target is stripped down to a single non-union type.
// Note
// * We actually want to remove null and undefined naively here (rather than using getNonNullableType),
// since we don't want to end up with a worse error like "`Foo` is not assignable to `NonNullable<T>`"
// when dealing with generics.
// * We also don't deal with primitive source types, since we already halt elaboration below.
if (target.flags & TypeFlags.Union && source.flags & TypeFlags.Object &&
(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 +12240,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 {

View File

@ -0,0 +1,31 @@
tests/cases/compiler/elaboratedErrorsOnNullableTargets01.ts(4,1): error TS2322: Type '{ foo: { bar: number; }; }' is not assignable to type '{ foo: { bar: string; }; }'.
Types of property 'foo' are incompatible.
Type '{ bar: number; }' is not assignable to type '{ bar: string; }'.
Types of property 'bar' are incompatible.
Type 'number' is not assignable to type 'string'.
tests/cases/compiler/elaboratedErrorsOnNullableTargets01.ts(6,1): error TS2322: Type '{ foo: { bar: string; }; }' is not assignable to type '{ foo: { bar: number; }; }'.
Types of property 'foo' are incompatible.
Type '{ bar: string; }' is not assignable to type '{ bar: number; }'.
Types of property 'bar' are incompatible.
Type 'string' is not assignable to type 'number'.
==== tests/cases/compiler/elaboratedErrorsOnNullableTargets01.ts (2 errors) ====
export declare let x: null | { foo: { bar: string | null } | undefined } | undefined;
export declare let y: { foo: { bar: number | undefined } };
x = y;
~
!!! error TS2322: Type '{ foo: { bar: number; }; }' is not assignable to type '{ foo: { bar: string; }; }'.
!!! error TS2322: Types of property 'foo' are incompatible.
!!! error TS2322: Type '{ bar: number; }' is not assignable to type '{ bar: string; }'.
!!! error TS2322: Types of property 'bar' are incompatible.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
y = x;
~
!!! error TS2322: Type '{ foo: { bar: string; }; }' is not assignable to type '{ foo: { bar: number; }; }'.
!!! error TS2322: Types of property 'foo' are incompatible.
!!! error TS2322: Type '{ bar: string; }' is not assignable to type '{ bar: number; }'.
!!! error TS2322: Types of property 'bar' are incompatible.
!!! error TS2322: Type 'string' is not assignable to type 'number'.

View File

@ -0,0 +1,13 @@
//// [elaboratedErrorsOnNullableTargets01.ts]
export declare let x: null | { foo: { bar: string | null } | undefined } | undefined;
export declare let y: { foo: { bar: number | undefined } };
x = y;
y = x;
//// [elaboratedErrorsOnNullableTargets01.js]
"use strict";
exports.__esModule = true;
exports.x = exports.y;
exports.y = exports.x;

View File

@ -0,0 +1,19 @@
=== tests/cases/compiler/elaboratedErrorsOnNullableTargets01.ts ===
export declare let x: null | { foo: { bar: string | null } | undefined } | undefined;
>x : Symbol(x, Decl(elaboratedErrorsOnNullableTargets01.ts, 0, 18))
>foo : Symbol(foo, Decl(elaboratedErrorsOnNullableTargets01.ts, 0, 30))
>bar : Symbol(bar, Decl(elaboratedErrorsOnNullableTargets01.ts, 0, 37))
export declare let y: { foo: { bar: number | undefined } };
>y : Symbol(y, Decl(elaboratedErrorsOnNullableTargets01.ts, 1, 18))
>foo : Symbol(foo, Decl(elaboratedErrorsOnNullableTargets01.ts, 1, 23))
>bar : Symbol(bar, Decl(elaboratedErrorsOnNullableTargets01.ts, 1, 30))
x = y;
>x : Symbol(x, Decl(elaboratedErrorsOnNullableTargets01.ts, 0, 18))
>y : Symbol(y, Decl(elaboratedErrorsOnNullableTargets01.ts, 1, 18))
y = x;
>y : Symbol(y, Decl(elaboratedErrorsOnNullableTargets01.ts, 1, 18))
>x : Symbol(x, Decl(elaboratedErrorsOnNullableTargets01.ts, 0, 18))

View File

@ -0,0 +1,23 @@
=== tests/cases/compiler/elaboratedErrorsOnNullableTargets01.ts ===
export declare let x: null | { foo: { bar: string | null } | undefined } | undefined;
>x : { foo: { bar: string; }; }
>null : null
>foo : { bar: string; }
>bar : string
>null : null
export declare let y: { foo: { bar: number | undefined } };
>y : { foo: { bar: number; }; }
>foo : { bar: number; }
>bar : number
x = y;
>x = y : { foo: { bar: number; }; }
>x : { foo: { bar: string; }; }
>y : { foo: { bar: number; }; }
y = x;
>y = x : { foo: { bar: string; }; }
>y : { foo: { bar: number; }; }
>x : { foo: { bar: string; }; }

View File

@ -1,10 +1,9 @@
tests/cases/compiler/nestedFreshLiteral.ts(12,21): error TS2322: Type '{ nested: { prop: { colour: string; }; }; }' is not assignable to type 'NestedCSSProps'.
Types of property 'nested' are incompatible.
Type '{ prop: { colour: string; }; }' is not assignable to type 'NestedSelector | undefined'.
Type '{ prop: { colour: string; }; }' is not assignable to type 'NestedSelector'.
Types of property 'prop' are incompatible.
Type '{ colour: string; }' is not assignable to type 'CSSProps'.
Object literal may only specify known properties, but 'colour' does not exist in type 'CSSProps'. Did you mean to write 'color'?
Type '{ prop: { colour: string; }; }' is not assignable to type 'NestedSelector'.
Types of property 'prop' are incompatible.
Type '{ colour: string; }' is not assignable to type 'CSSProps'.
Object literal may only specify known properties, but 'colour' does not exist in type 'CSSProps'. Did you mean to write 'color'?
==== tests/cases/compiler/nestedFreshLiteral.ts (1 errors) ====
@ -23,9 +22,8 @@ tests/cases/compiler/nestedFreshLiteral.ts(12,21): error TS2322: Type '{ nested:
~~~~~~~~~~~~~
!!! error TS2322: Type '{ nested: { prop: { colour: string; }; }; }' is not assignable to type 'NestedCSSProps'.
!!! error TS2322: Types of property 'nested' are incompatible.
!!! error TS2322: Type '{ prop: { colour: string; }; }' is not assignable to type 'NestedSelector | undefined'.
!!! error TS2322: Type '{ prop: { colour: string; }; }' is not assignable to type 'NestedSelector'.
!!! error TS2322: Types of property 'prop' are incompatible.
!!! error TS2322: Type '{ colour: string; }' is not assignable to type 'CSSProps'.
!!! error TS2322: Object literal may only specify known properties, but 'colour' does not exist in type 'CSSProps'. Did you mean to write 'color'?
!!! error TS2322: Type '{ prop: { colour: string; }; }' is not assignable to type 'NestedSelector'.
!!! error TS2322: Types of property 'prop' are incompatible.
!!! error TS2322: Type '{ colour: string; }' is not assignable to type 'CSSProps'.
!!! error TS2322: Object literal may only specify known properties, but 'colour' does not exist in type 'CSSProps'. Did you mean to write 'color'?
}

View File

@ -0,0 +1,7 @@
export declare let x: null | { foo: { bar: string | null } | undefined } | undefined;
export declare let y: { foo: { bar: number | undefined } };
x = y;
y = x;