improve error message when type have same name (#27065)
* improve error message when type have same name * fix lint and function name * update test case * accept baseline
This commit is contained in:
parent
a3c852db9b
commit
bd178746de
|
@ -3322,6 +3322,16 @@ namespace ts {
|
|||
return result;
|
||||
}
|
||||
|
||||
function getTypeNamesForErrorDisplay(left: Type, right: Type): [string, string] {
|
||||
let leftStr = typeToString(left);
|
||||
let rightStr = typeToString(right);
|
||||
if (leftStr === rightStr) {
|
||||
leftStr = typeToString(left, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
|
||||
rightStr = typeToString(right, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
|
||||
}
|
||||
return [leftStr, rightStr];
|
||||
}
|
||||
|
||||
function toNodeBuilderFlags(flags = TypeFormatFlags.None): NodeBuilderFlags {
|
||||
return flags & TypeFormatFlags.NodeBuilderFlagsMask;
|
||||
}
|
||||
|
@ -12253,12 +12263,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function reportRelationError(message: DiagnosticMessage | undefined, source: Type, target: Type) {
|
||||
let sourceType = typeToString(source);
|
||||
let targetType = typeToString(target);
|
||||
if (sourceType === targetType) {
|
||||
sourceType = typeToString(source, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
|
||||
targetType = typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
|
||||
}
|
||||
const [sourceType, targetType] = getTypeNamesForErrorDisplay(source, target);
|
||||
|
||||
if (!message) {
|
||||
if (relation === comparableRelation) {
|
||||
|
@ -13209,7 +13214,7 @@ namespace ts {
|
|||
}
|
||||
if (props.length === 1) {
|
||||
const propName = symbolToString(unmatchedProperty);
|
||||
reportError(Diagnostics.Property_0_is_missing_in_type_1_but_required_in_type_2, propName, typeToString(source), typeToString(target));
|
||||
reportError(Diagnostics.Property_0_is_missing_in_type_1_but_required_in_type_2, propName, ...getTypeNamesForErrorDisplay(source, target));
|
||||
if (length(unmatchedProperty.declarations)) {
|
||||
associateRelatedInfo(createDiagnosticForNode(unmatchedProperty.declarations[0], Diagnostics._0_is_declared_here, propName));
|
||||
}
|
||||
|
@ -23452,8 +23457,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function reportOperatorError() {
|
||||
const leftStr = typeToString(leftType);
|
||||
const rightStr = typeToString(rightType);
|
||||
const [leftStr, rightStr] = getTypeNamesForErrorDisplay(leftType, rightType);
|
||||
const errNode = errorNode || operatorToken;
|
||||
if (!tryGiveBetterPrimaryError(errNode, leftStr, rightStr)) {
|
||||
error(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
tests/cases/compiler/clodulesDerivedClasses.ts(9,7): error TS2417: Class static side 'typeof Path' incorrectly extends base class static side 'typeof Shape'.
|
||||
Types of property 'Utils' are incompatible.
|
||||
Property 'convert' is missing in type 'typeof Utils' but required in type 'typeof Utils'.
|
||||
Property 'convert' is missing in type 'typeof Path.Utils' but required in type 'typeof Shape.Utils'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/clodulesDerivedClasses.ts (1 errors) ====
|
||||
|
@ -16,7 +16,7 @@ tests/cases/compiler/clodulesDerivedClasses.ts(9,7): error TS2417: Class static
|
|||
~~~~
|
||||
!!! error TS2417: Class static side 'typeof Path' incorrectly extends base class static side 'typeof Shape'.
|
||||
!!! error TS2417: Types of property 'Utils' are incompatible.
|
||||
!!! error TS2417: Property 'convert' is missing in type 'typeof Utils' but required in type 'typeof Utils'.
|
||||
!!! error TS2417: Property 'convert' is missing in type 'typeof Path.Utils' but required in type 'typeof Shape.Utils'.
|
||||
!!! related TS2728 tests/cases/compiler/clodulesDerivedClasses.ts:6:21: 'convert' is declared here.
|
||||
name: string;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
tests/cases/compiler/differentTypesWithSameName.ts(16,15): error TS2345: Argument of type 'variable' is not assignable to parameter of type 'm.variable'.
|
||||
Property 's' is missing in type 'variable' but required in type 'variable'.
|
||||
Property 's' is missing in type 'variable' but required in type 'm.variable'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/differentTypesWithSameName.ts (1 errors) ====
|
||||
|
@ -21,5 +21,5 @@ tests/cases/compiler/differentTypesWithSameName.ts(16,15): error TS2345: Argumen
|
|||
m.doSomething(v);
|
||||
~
|
||||
!!! error TS2345: Argument of type 'variable' is not assignable to parameter of type 'm.variable'.
|
||||
!!! error TS2345: Property 's' is missing in type 'variable' but required in type 'variable'.
|
||||
!!! error TS2345: Property 's' is missing in type 'variable' but required in type 'm.variable'.
|
||||
!!! related TS2728 tests/cases/compiler/differentTypesWithSameName.ts:3:5: 's' is declared here.
|
32
tests/baselines/reference/errorWithSameNameType.errors.txt
Normal file
32
tests/baselines/reference/errorWithSameNameType.errors.txt
Normal file
|
@ -0,0 +1,32 @@
|
|||
tests/cases/compiler/c.ts(7,5): error TS2367: This condition will always return 'false' since the types 'import("tests/cases/compiler/a").F' and 'import("tests/cases/compiler/b").F' have no overlap.
|
||||
tests/cases/compiler/c.ts(11,1): error TS2741: Property 'foo1' is missing in type 'import("tests/cases/compiler/b").F' but required in type 'import("tests/cases/compiler/a").F'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/a.ts (0 errors) ====
|
||||
export interface F {
|
||||
foo1: number
|
||||
}
|
||||
|
||||
==== tests/cases/compiler/b.ts (0 errors) ====
|
||||
export interface F {
|
||||
foo2: number
|
||||
}
|
||||
|
||||
==== tests/cases/compiler/c.ts (2 errors) ====
|
||||
import * as A from './a'
|
||||
import * as B from './b'
|
||||
|
||||
let a: A.F
|
||||
let b: B.F
|
||||
|
||||
if (a === b) {
|
||||
~~~~~~~
|
||||
!!! error TS2367: This condition will always return 'false' since the types 'import("tests/cases/compiler/a").F' and 'import("tests/cases/compiler/b").F' have no overlap.
|
||||
|
||||
}
|
||||
|
||||
a = b
|
||||
~
|
||||
!!! error TS2741: Property 'foo1' is missing in type 'import("tests/cases/compiler/b").F' but required in type 'import("tests/cases/compiler/a").F'.
|
||||
!!! related TS2728 tests/cases/compiler/a.ts:2:5: 'foo1' is declared here.
|
||||
|
40
tests/baselines/reference/errorWithSameNameType.js
Normal file
40
tests/baselines/reference/errorWithSameNameType.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
//// [tests/cases/compiler/errorWithSameNameType.ts] ////
|
||||
|
||||
//// [a.ts]
|
||||
export interface F {
|
||||
foo1: number
|
||||
}
|
||||
|
||||
//// [b.ts]
|
||||
export interface F {
|
||||
foo2: number
|
||||
}
|
||||
|
||||
//// [c.ts]
|
||||
import * as A from './a'
|
||||
import * as B from './b'
|
||||
|
||||
let a: A.F
|
||||
let b: B.F
|
||||
|
||||
if (a === b) {
|
||||
|
||||
}
|
||||
|
||||
a = b
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
//// [b.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
//// [c.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var a;
|
||||
var b;
|
||||
if (a === b) {
|
||||
}
|
||||
a = b;
|
43
tests/baselines/reference/errorWithSameNameType.symbols
Normal file
43
tests/baselines/reference/errorWithSameNameType.symbols
Normal file
|
@ -0,0 +1,43 @@
|
|||
=== tests/cases/compiler/a.ts ===
|
||||
export interface F {
|
||||
>F : Symbol(F, Decl(a.ts, 0, 0))
|
||||
|
||||
foo1: number
|
||||
>foo1 : Symbol(F.foo1, Decl(a.ts, 0, 20))
|
||||
}
|
||||
|
||||
=== tests/cases/compiler/b.ts ===
|
||||
export interface F {
|
||||
>F : Symbol(F, Decl(b.ts, 0, 0))
|
||||
|
||||
foo2: number
|
||||
>foo2 : Symbol(F.foo2, Decl(b.ts, 0, 20))
|
||||
}
|
||||
|
||||
=== tests/cases/compiler/c.ts ===
|
||||
import * as A from './a'
|
||||
>A : Symbol(A, Decl(c.ts, 0, 6))
|
||||
|
||||
import * as B from './b'
|
||||
>B : Symbol(B, Decl(c.ts, 1, 6))
|
||||
|
||||
let a: A.F
|
||||
>a : Symbol(a, Decl(c.ts, 3, 3))
|
||||
>A : Symbol(A, Decl(c.ts, 0, 6))
|
||||
>F : Symbol(A.F, Decl(a.ts, 0, 0))
|
||||
|
||||
let b: B.F
|
||||
>b : Symbol(b, Decl(c.ts, 4, 3))
|
||||
>B : Symbol(B, Decl(c.ts, 1, 6))
|
||||
>F : Symbol(B.F, Decl(b.ts, 0, 0))
|
||||
|
||||
if (a === b) {
|
||||
>a : Symbol(a, Decl(c.ts, 3, 3))
|
||||
>b : Symbol(b, Decl(c.ts, 4, 3))
|
||||
|
||||
}
|
||||
|
||||
a = b
|
||||
>a : Symbol(a, Decl(c.ts, 3, 3))
|
||||
>b : Symbol(b, Decl(c.ts, 4, 3))
|
||||
|
39
tests/baselines/reference/errorWithSameNameType.types
Normal file
39
tests/baselines/reference/errorWithSameNameType.types
Normal file
|
@ -0,0 +1,39 @@
|
|||
=== tests/cases/compiler/a.ts ===
|
||||
export interface F {
|
||||
foo1: number
|
||||
>foo1 : number
|
||||
}
|
||||
|
||||
=== tests/cases/compiler/b.ts ===
|
||||
export interface F {
|
||||
foo2: number
|
||||
>foo2 : number
|
||||
}
|
||||
|
||||
=== tests/cases/compiler/c.ts ===
|
||||
import * as A from './a'
|
||||
>A : typeof A
|
||||
|
||||
import * as B from './b'
|
||||
>B : typeof B
|
||||
|
||||
let a: A.F
|
||||
>a : A.F
|
||||
>A : any
|
||||
|
||||
let b: B.F
|
||||
>b : B.F
|
||||
>B : any
|
||||
|
||||
if (a === b) {
|
||||
>a === b : boolean
|
||||
>a : A.F
|
||||
>b : B.F
|
||||
|
||||
}
|
||||
|
||||
a = b
|
||||
>a = b : B.F
|
||||
>a : A.F
|
||||
>b : B.F
|
||||
|
|
@ -19,7 +19,7 @@ tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAnd
|
|||
tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAndInvalidInitializer.ts(50,5): error TS2322: Type 'typeof N' is not assignable to type 'typeof M'.
|
||||
Types of property 'A' are incompatible.
|
||||
Type 'typeof N.A' is not assignable to type 'typeof M.A'.
|
||||
Property 'name' is missing in type 'A' but required in type 'A'.
|
||||
Property 'name' is missing in type 'N.A' but required in type 'M.A'.
|
||||
tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAndInvalidInitializer.ts(51,5): error TS2322: Type 'N.A' is not assignable to type 'M.A'.
|
||||
tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAndInvalidInitializer.ts(52,5): error TS2322: Type '(x: number) => boolean' is not assignable to type '(x: number) => string'.
|
||||
Type 'boolean' is not assignable to type 'string'.
|
||||
|
@ -114,7 +114,7 @@ tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAnd
|
|||
!!! error TS2322: Type 'typeof N' is not assignable to type 'typeof M'.
|
||||
!!! error TS2322: Types of property 'A' are incompatible.
|
||||
!!! error TS2322: Type 'typeof N.A' is not assignable to type 'typeof M.A'.
|
||||
!!! error TS2322: Property 'name' is missing in type 'A' but required in type 'A'.
|
||||
!!! error TS2322: Property 'name' is missing in type 'N.A' but required in type 'M.A'.
|
||||
!!! related TS2728 tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAndInvalidInitializer.ts:20:9: 'name' is declared here.
|
||||
var aClassInModule: M.A = new N.A();
|
||||
~~~~~~~~~~~~~~
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
tests/cases/conformance/jsx/inline/index.tsx(5,1): error TS2741: Property '__predomBrand' is missing in type 'Element' but required in type 'Element'.
|
||||
tests/cases/conformance/jsx/inline/index.tsx(5,1): error TS2741: Property '__predomBrand' is missing in type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element' but required in type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element'.
|
||||
tests/cases/conformance/jsx/inline/index.tsx(21,40): error TS2322: Type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element' is not assignable to type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element'.
|
||||
tests/cases/conformance/jsx/inline/index.tsx(21,40): error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
|
||||
Property '__domBrand' is missing in type 'MyClass' but required in type 'ElementClass'.
|
||||
tests/cases/conformance/jsx/inline/index.tsx(21,63): error TS2322: Type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element' is not assignable to type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element'.
|
||||
tests/cases/conformance/jsx/inline/index.tsx(21,63): error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
|
||||
tests/cases/conformance/jsx/inline/index.tsx(24,42): error TS2741: Property '__domBrand' is missing in type 'Element' but required in type 'Element'.
|
||||
tests/cases/conformance/jsx/inline/index.tsx(24,42): error TS2741: Property '__domBrand' is missing in type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element' but required in type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element'.
|
||||
tests/cases/conformance/jsx/inline/index.tsx(24,48): error TS2322: Type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element' is not assignable to type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element'.
|
||||
|
||||
|
||||
|
@ -75,7 +75,7 @@ tests/cases/conformance/jsx/inline/index.tsx(24,48): error TS2322: Type 'import(
|
|||
let elem = prerendered;
|
||||
elem = <h></h>; // Expect assignability error here
|
||||
~~~~
|
||||
!!! error TS2741: Property '__predomBrand' is missing in type 'Element' but required in type 'Element'.
|
||||
!!! error TS2741: Property '__predomBrand' is missing in type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element' but required in type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element'.
|
||||
!!! related TS2728 tests/cases/conformance/jsx/inline/renderer2.d.ts:7:13: '__predomBrand' is declared here.
|
||||
|
||||
const DOMSFC = (props: {x: number, y: number, children?: dom.JSX.Element[]}) => <p>{props.x} + {props.y} = {props.x + props.y}{props.children}</p>;
|
||||
|
@ -107,7 +107,7 @@ tests/cases/conformance/jsx/inline/index.tsx(24,48): error TS2322: Type 'import(
|
|||
// Should fail, nondom isn't allowed as children of dom
|
||||
const _brokenTree2 = <DOMSFC x={1} y={2}>{tree}{tree}</DOMSFC>
|
||||
~~~~~~
|
||||
!!! error TS2741: Property '__domBrand' is missing in type 'Element' but required in type 'Element'.
|
||||
!!! error TS2741: Property '__domBrand' is missing in type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element' but required in type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element'.
|
||||
!!! related TS2728 tests/cases/conformance/jsx/inline/renderer.d.ts:7:13: '__domBrand' is declared here.
|
||||
~~~~~~
|
||||
!!! error TS2322: Type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element' is not assignable to type 'import("tests/cases/conformance/jsx/inline/renderer").dom.JSX.Element'.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
tests/cases/conformance/jsx/inline/index.tsx(5,1): error TS2741: Property '__predomBrand' is missing in type 'Element' but required in type 'Element'.
|
||||
tests/cases/conformance/jsx/inline/index.tsx(5,1): error TS2741: Property '__predomBrand' is missing in type 'JSX.Element' but required in type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsx/inline/renderer.d.ts (0 errors) ====
|
||||
|
@ -45,6 +45,6 @@ tests/cases/conformance/jsx/inline/index.tsx(5,1): error TS2741: Property '__pre
|
|||
let elem = prerendered;
|
||||
elem = <h></h>; // Expect assignability error here
|
||||
~~~~
|
||||
!!! error TS2741: Property '__predomBrand' is missing in type 'Element' but required in type 'Element'.
|
||||
!!! error TS2741: Property '__predomBrand' is missing in type 'JSX.Element' but required in type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element'.
|
||||
!!! related TS2728 tests/cases/conformance/jsx/inline/renderer2.d.ts:7:13: '__predomBrand' is declared here.
|
||||
|
|
@ -7,7 +7,7 @@ tests/cases/compiler/qualify.ts(47,13): error TS2322: Type 'I4' is not assignabl
|
|||
tests/cases/compiler/qualify.ts(48,13): error TS2322: Type 'I4' is not assignable to type '(k: I3) => void'.
|
||||
Type 'I4' provides no match for the signature '(k: I3): void'.
|
||||
tests/cases/compiler/qualify.ts(49,13): error TS2741: Property 'k' is missing in type 'I4' but required in type '{ k: I3; }'.
|
||||
tests/cases/compiler/qualify.ts(58,5): error TS2741: Property 'p' is missing in type 'I' but required in type 'I'.
|
||||
tests/cases/compiler/qualify.ts(58,5): error TS2741: Property 'p' is missing in type 'I' but required in type 'T.I'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/qualify.ts (8 errors) ====
|
||||
|
@ -88,7 +88,7 @@ tests/cases/compiler/qualify.ts(58,5): error TS2741: Property 'p' is missing in
|
|||
var y:I;
|
||||
var x:T.I=y;
|
||||
~
|
||||
!!! error TS2741: Property 'p' is missing in type 'I' but required in type 'I'.
|
||||
!!! error TS2741: Property 'p' is missing in type 'I' but required in type 'T.I'.
|
||||
!!! related TS2728 tests/cases/compiler/qualify.ts:18:9: 'p' is declared here.
|
||||
|
||||
|
22
tests/cases/compiler/errorWithSameNameType.ts
Normal file
22
tests/cases/compiler/errorWithSameNameType.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
// @filename: a.ts
|
||||
export interface F {
|
||||
foo1: number
|
||||
}
|
||||
|
||||
// @filename: b.ts
|
||||
export interface F {
|
||||
foo2: number
|
||||
}
|
||||
|
||||
// @filename: c.ts
|
||||
import * as A from './a'
|
||||
import * as B from './b'
|
||||
|
||||
let a: A.F
|
||||
let b: B.F
|
||||
|
||||
if (a === b) {
|
||||
|
||||
}
|
||||
|
||||
a = b
|
Loading…
Reference in a new issue