Skip to content

Commit bd17874

Browse files
KingwlRyanCavanaugh
authored andcommitted
improve error message when type have same name (microsoft#27065)
* improve error message when type have same name * fix lint and function name * update test case * accept baseline
1 parent a3c852d commit bd17874

12 files changed

+203
-23
lines changed

src/compiler/checker.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3322,6 +3322,16 @@ namespace ts {
33223322
return result;
33233323
}
33243324

3325+
function getTypeNamesForErrorDisplay(left: Type, right: Type): [string, string] {
3326+
let leftStr = typeToString(left);
3327+
let rightStr = typeToString(right);
3328+
if (leftStr === rightStr) {
3329+
leftStr = typeToString(left, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
3330+
rightStr = typeToString(right, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
3331+
}
3332+
return [leftStr, rightStr];
3333+
}
3334+
33253335
function toNodeBuilderFlags(flags = TypeFormatFlags.None): NodeBuilderFlags {
33263336
return flags & TypeFormatFlags.NodeBuilderFlagsMask;
33273337
}
@@ -12253,12 +12263,7 @@ namespace ts {
1225312263
}
1225412264

1225512265
function reportRelationError(message: DiagnosticMessage | undefined, source: Type, target: Type) {
12256-
let sourceType = typeToString(source);
12257-
let targetType = typeToString(target);
12258-
if (sourceType === targetType) {
12259-
sourceType = typeToString(source, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
12260-
targetType = typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
12261-
}
12266+
const [sourceType, targetType] = getTypeNamesForErrorDisplay(source, target);
1226212267

1226312268
if (!message) {
1226412269
if (relation === comparableRelation) {
@@ -13209,7 +13214,7 @@ namespace ts {
1320913214
}
1321013215
if (props.length === 1) {
1321113216
const propName = symbolToString(unmatchedProperty);
13212-
reportError(Diagnostics.Property_0_is_missing_in_type_1_but_required_in_type_2, propName, typeToString(source), typeToString(target));
13217+
reportError(Diagnostics.Property_0_is_missing_in_type_1_but_required_in_type_2, propName, ...getTypeNamesForErrorDisplay(source, target));
1321313218
if (length(unmatchedProperty.declarations)) {
1321413219
associateRelatedInfo(createDiagnosticForNode(unmatchedProperty.declarations[0], Diagnostics._0_is_declared_here, propName));
1321513220
}
@@ -23452,8 +23457,7 @@ namespace ts {
2345223457
}
2345323458

2345423459
function reportOperatorError() {
23455-
const leftStr = typeToString(leftType);
23456-
const rightStr = typeToString(rightType);
23460+
const [leftStr, rightStr] = getTypeNamesForErrorDisplay(leftType, rightType);
2345723461
const errNode = errorNode || operatorToken;
2345823462
if (!tryGiveBetterPrimaryError(errNode, leftStr, rightStr)) {
2345923463
error(

tests/baselines/reference/clodulesDerivedClasses.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
tests/cases/compiler/clodulesDerivedClasses.ts(9,7): error TS2417: Class static side 'typeof Path' incorrectly extends base class static side 'typeof Shape'.
22
Types of property 'Utils' are incompatible.
3-
Property 'convert' is missing in type 'typeof Utils' but required in type 'typeof Utils'.
3+
Property 'convert' is missing in type 'typeof Path.Utils' but required in type 'typeof Shape.Utils'.
44

55

66
==== tests/cases/compiler/clodulesDerivedClasses.ts (1 errors) ====
@@ -16,7 +16,7 @@ tests/cases/compiler/clodulesDerivedClasses.ts(9,7): error TS2417: Class static
1616
~~~~
1717
!!! error TS2417: Class static side 'typeof Path' incorrectly extends base class static side 'typeof Shape'.
1818
!!! error TS2417: Types of property 'Utils' are incompatible.
19-
!!! error TS2417: Property 'convert' is missing in type 'typeof Utils' but required in type 'typeof Utils'.
19+
!!! error TS2417: Property 'convert' is missing in type 'typeof Path.Utils' but required in type 'typeof Shape.Utils'.
2020
!!! related TS2728 tests/cases/compiler/clodulesDerivedClasses.ts:6:21: 'convert' is declared here.
2121
name: string;
2222

tests/baselines/reference/differentTypesWithSameName.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
tests/cases/compiler/differentTypesWithSameName.ts(16,15): error TS2345: Argument of type 'variable' is not assignable to parameter of type 'm.variable'.
2-
Property 's' is missing in type 'variable' but required in type 'variable'.
2+
Property 's' is missing in type 'variable' but required in type 'm.variable'.
33

44

55
==== tests/cases/compiler/differentTypesWithSameName.ts (1 errors) ====
@@ -21,5 +21,5 @@ tests/cases/compiler/differentTypesWithSameName.ts(16,15): error TS2345: Argumen
2121
m.doSomething(v);
2222
~
2323
!!! error TS2345: Argument of type 'variable' is not assignable to parameter of type 'm.variable'.
24-
!!! error TS2345: Property 's' is missing in type 'variable' but required in type 'variable'.
24+
!!! error TS2345: Property 's' is missing in type 'variable' but required in type 'm.variable'.
2525
!!! related TS2728 tests/cases/compiler/differentTypesWithSameName.ts:3:5: 's' is declared here.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
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.
2+
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'.
3+
4+
5+
==== tests/cases/compiler/a.ts (0 errors) ====
6+
export interface F {
7+
foo1: number
8+
}
9+
10+
==== tests/cases/compiler/b.ts (0 errors) ====
11+
export interface F {
12+
foo2: number
13+
}
14+
15+
==== tests/cases/compiler/c.ts (2 errors) ====
16+
import * as A from './a'
17+
import * as B from './b'
18+
19+
let a: A.F
20+
let b: B.F
21+
22+
if (a === b) {
23+
~~~~~~~
24+
!!! 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.
25+
26+
}
27+
28+
a = b
29+
~
30+
!!! error TS2741: Property 'foo1' is missing in type 'import("tests/cases/compiler/b").F' but required in type 'import("tests/cases/compiler/a").F'.
31+
!!! related TS2728 tests/cases/compiler/a.ts:2:5: 'foo1' is declared here.
32+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//// [tests/cases/compiler/errorWithSameNameType.ts] ////
2+
3+
//// [a.ts]
4+
export interface F {
5+
foo1: number
6+
}
7+
8+
//// [b.ts]
9+
export interface F {
10+
foo2: number
11+
}
12+
13+
//// [c.ts]
14+
import * as A from './a'
15+
import * as B from './b'
16+
17+
let a: A.F
18+
let b: B.F
19+
20+
if (a === b) {
21+
22+
}
23+
24+
a = b
25+
26+
27+
//// [a.js]
28+
"use strict";
29+
exports.__esModule = true;
30+
//// [b.js]
31+
"use strict";
32+
exports.__esModule = true;
33+
//// [c.js]
34+
"use strict";
35+
exports.__esModule = true;
36+
var a;
37+
var b;
38+
if (a === b) {
39+
}
40+
a = b;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
=== tests/cases/compiler/a.ts ===
2+
export interface F {
3+
>F : Symbol(F, Decl(a.ts, 0, 0))
4+
5+
foo1: number
6+
>foo1 : Symbol(F.foo1, Decl(a.ts, 0, 20))
7+
}
8+
9+
=== tests/cases/compiler/b.ts ===
10+
export interface F {
11+
>F : Symbol(F, Decl(b.ts, 0, 0))
12+
13+
foo2: number
14+
>foo2 : Symbol(F.foo2, Decl(b.ts, 0, 20))
15+
}
16+
17+
=== tests/cases/compiler/c.ts ===
18+
import * as A from './a'
19+
>A : Symbol(A, Decl(c.ts, 0, 6))
20+
21+
import * as B from './b'
22+
>B : Symbol(B, Decl(c.ts, 1, 6))
23+
24+
let a: A.F
25+
>a : Symbol(a, Decl(c.ts, 3, 3))
26+
>A : Symbol(A, Decl(c.ts, 0, 6))
27+
>F : Symbol(A.F, Decl(a.ts, 0, 0))
28+
29+
let b: B.F
30+
>b : Symbol(b, Decl(c.ts, 4, 3))
31+
>B : Symbol(B, Decl(c.ts, 1, 6))
32+
>F : Symbol(B.F, Decl(b.ts, 0, 0))
33+
34+
if (a === b) {
35+
>a : Symbol(a, Decl(c.ts, 3, 3))
36+
>b : Symbol(b, Decl(c.ts, 4, 3))
37+
38+
}
39+
40+
a = b
41+
>a : Symbol(a, Decl(c.ts, 3, 3))
42+
>b : Symbol(b, Decl(c.ts, 4, 3))
43+
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
=== tests/cases/compiler/a.ts ===
2+
export interface F {
3+
foo1: number
4+
>foo1 : number
5+
}
6+
7+
=== tests/cases/compiler/b.ts ===
8+
export interface F {
9+
foo2: number
10+
>foo2 : number
11+
}
12+
13+
=== tests/cases/compiler/c.ts ===
14+
import * as A from './a'
15+
>A : typeof A
16+
17+
import * as B from './b'
18+
>B : typeof B
19+
20+
let a: A.F
21+
>a : A.F
22+
>A : any
23+
24+
let b: B.F
25+
>b : B.F
26+
>B : any
27+
28+
if (a === b) {
29+
>a === b : boolean
30+
>a : A.F
31+
>b : B.F
32+
33+
}
34+
35+
a = b
36+
>a = b : B.F
37+
>a : A.F
38+
>b : B.F
39+

tests/baselines/reference/everyTypeWithAnnotationAndInvalidInitializer.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAnd
1919
tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAndInvalidInitializer.ts(50,5): error TS2322: Type 'typeof N' is not assignable to type 'typeof M'.
2020
Types of property 'A' are incompatible.
2121
Type 'typeof N.A' is not assignable to type 'typeof M.A'.
22-
Property 'name' is missing in type 'A' but required in type 'A'.
22+
Property 'name' is missing in type 'N.A' but required in type 'M.A'.
2323
tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAndInvalidInitializer.ts(51,5): error TS2322: Type 'N.A' is not assignable to type 'M.A'.
2424
tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAndInvalidInitializer.ts(52,5): error TS2322: Type '(x: number) => boolean' is not assignable to type '(x: number) => string'.
2525
Type 'boolean' is not assignable to type 'string'.
@@ -114,7 +114,7 @@ tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAnd
114114
!!! error TS2322: Type 'typeof N' is not assignable to type 'typeof M'.
115115
!!! error TS2322: Types of property 'A' are incompatible.
116116
!!! error TS2322: Type 'typeof N.A' is not assignable to type 'typeof M.A'.
117-
!!! error TS2322: Property 'name' is missing in type 'A' but required in type 'A'.
117+
!!! error TS2322: Property 'name' is missing in type 'N.A' but required in type 'M.A'.
118118
!!! related TS2728 tests/cases/conformance/statements/VariableStatements/everyTypeWithAnnotationAndInvalidInitializer.ts:20:9: 'name' is declared here.
119119
var aClassInModule: M.A = new N.A();
120120
~~~~~~~~~~~~~~

tests/baselines/reference/inlineJsxFactoryDeclarationsLocalTypes.errors.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
tests/cases/conformance/jsx/inline/index.tsx(5,1): error TS2741: Property '__predomBrand' is missing in type 'Element' but required in type 'Element'.
1+
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'.
22
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'.
33
tests/cases/conformance/jsx/inline/index.tsx(21,40): error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
44
Property '__domBrand' is missing in type 'MyClass' but required in type 'ElementClass'.
55
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'.
66
tests/cases/conformance/jsx/inline/index.tsx(21,63): error TS2605: JSX element type 'MyClass' is not a constructor function for JSX elements.
7-
tests/cases/conformance/jsx/inline/index.tsx(24,42): error TS2741: Property '__domBrand' is missing in type 'Element' but required in type 'Element'.
7+
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'.
88
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'.
99

1010

@@ -75,7 +75,7 @@ tests/cases/conformance/jsx/inline/index.tsx(24,48): error TS2322: Type 'import(
7575
let elem = prerendered;
7676
elem = <h></h>; // Expect assignability error here
7777
~~~~
78-
!!! error TS2741: Property '__predomBrand' is missing in type 'Element' but required in type 'Element'.
78+
!!! 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'.
7979
!!! related TS2728 tests/cases/conformance/jsx/inline/renderer2.d.ts:7:13: '__predomBrand' is declared here.
8080

8181
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(
107107
// Should fail, nondom isn't allowed as children of dom
108108
const _brokenTree2 = <DOMSFC x={1} y={2}>{tree}{tree}</DOMSFC>
109109
~~~~~~
110-
!!! error TS2741: Property '__domBrand' is missing in type 'Element' but required in type 'Element'.
110+
!!! 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'.
111111
!!! related TS2728 tests/cases/conformance/jsx/inline/renderer.d.ts:7:13: '__domBrand' is declared here.
112112
~~~~~~
113113
!!! 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'.

tests/baselines/reference/inlineJsxFactoryLocalTypeGlobalFallback.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tests/cases/conformance/jsx/inline/index.tsx(5,1): error TS2741: Property '__predomBrand' is missing in type 'Element' but required in type 'Element'.
1+
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'.
22

33

44
==== 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
4545
let elem = prerendered;
4646
elem = <h></h>; // Expect assignability error here
4747
~~~~
48-
!!! error TS2741: Property '__predomBrand' is missing in type 'Element' but required in type 'Element'.
48+
!!! error TS2741: Property '__predomBrand' is missing in type 'JSX.Element' but required in type 'import("tests/cases/conformance/jsx/inline/renderer2").predom.JSX.Element'.
4949
!!! related TS2728 tests/cases/conformance/jsx/inline/renderer2.d.ts:7:13: '__predomBrand' is declared here.
5050

0 commit comments

Comments
 (0)