Skip to content

Commit 7366bc6

Browse files
committed
Clarify error message when an accessor is invoked.
1 parent 54a5be1 commit 7366bc6

File tree

4 files changed

+53
-12
lines changed

4 files changed

+53
-12
lines changed

src/compiler/checker.ts

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20061,13 +20061,47 @@ namespace ts {
2006120061
}
2006220062
else {
2006320063
let relatedInformation: DiagnosticRelatedInformation | undefined;
20064+
let propertyName: string | undefined;
20065+
let propertyAccessorText: string | undefined;
2006420066
if (node.arguments.length === 1 && isTypeAssertion(first(node.arguments))) {
2006520067
const text = getSourceFileOfNode(node).text;
2006620068
if (isLineBreak(text.charCodeAt(skipTrivia(text, node.expression.end, /* stopAfterLineBreak */ true) - 1))) {
2006720069
relatedInformation = createDiagnosticForNode(node.expression, Diagnostics.It_is_highly_likely_that_you_are_missing_a_semicolon);
2006820070
}
2006920071
}
20070-
invocationError(node, apparentType, SignatureKind.Call, relatedInformation);
20072+
else if (node.expression.kind === SyntaxKind.PropertyAccessExpression) {
20073+
const propertyAccess = node.expression as PropertyAccessExpression;
20074+
const symbol = getSymbolOfEntityNameOrPropertyAccessExpression(propertyAccess);
20075+
20076+
// Handle union types with non-function-like signatures.
20077+
if (symbol) {
20078+
const links = getSymbolLinks(symbol);
20079+
const isObjectUnionOrIntersection = links && links.type && (
20080+
(links.type.flags & (TypeFlags.Union | TypeFlags.Intersection | TypeFlags.Object)) !== 0
20081+
) || false;
20082+
20083+
let invokable = isObjectUnionOrIntersection;
20084+
if (isObjectUnionOrIntersection) {
20085+
if (links && links.type && (links.type.flags & TypeFlags.Object)) {
20086+
const resolvedType = links.type as ObjectType;
20087+
invokable = (resolvedType.callSignatures && resolvedType.callSignatures.length !== 0) || false;
20088+
}
20089+
else {
20090+
const resolvedType = links.type as UnionOrIntersectionType;
20091+
invokable = every(resolvedType.types, ty => (ty as ResolvedType).callSignatures && (ty as ResolvedType).callSignatures.length !== 0);
20092+
}
20093+
}
20094+
20095+
if (!invokable) {
20096+
const file = getSourceFileOfNode(node);
20097+
20098+
propertyName = propertyAccess.name.escapedText.toString();
20099+
propertyAccessorText = createPrinter().printNode(EmitHint.Expression, propertyAccess, file);
20100+
}
20101+
}
20102+
}
20103+
20104+
invocationError(node, apparentType, SignatureKind.Call, relatedInformation, propertyName, propertyAccessorText);
2007120105
}
2007220106
return resolveErrorCall(node);
2007320107
}
@@ -20237,11 +20271,14 @@ namespace ts {
2023720271
return true;
2023820272
}
2023920273

20240-
function invocationError(node: Node, apparentType: Type, kind: SignatureKind, relatedInformation?: DiagnosticRelatedInformation) {
20274+
function invocationError(node: Node, apparentType: Type, kind: SignatureKind, relatedInformation?: DiagnosticRelatedInformation, propertyName?: string, didYouMean?: string) {
2024120275
const diagnostic = error(node, (kind === SignatureKind.Call ?
20242-
Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures :
20276+
(propertyName === undefined ?
20277+
Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures :
20278+
Diagnostics.Cannot_invoke_expression_1_which_is_a_property_and_has_the_type_0_which_has_no_compatible_call_signature_Did_you_mean_2
20279+
) :
2024320280
Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature
20244-
), typeToString(apparentType));
20281+
), typeToString(apparentType), propertyName, didYouMean);
2024520282
invocationErrorRecovery(apparentType, kind, relatedInformation ? addRelatedInfo(diagnostic, relatedInformation) : diagnostic);
2024620283
}
2024720284

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2489,6 +2489,10 @@
24892489
"category": "Error",
24902490
"code": 2734
24912491
},
2492+
"Cannot invoke expression `{1}`, which is a property and has the type `{0}` which has no compatible call signature. Did you mean `{2}`": {
2493+
"category": "Error",
2494+
"code": 2735
2495+
},
24922496

24932497
"Import declaration '{0}' is using private name '{1}'.": {
24942498
"category": "Error",

tests/baselines/reference/instancePropertiesInheritedIntoClassType.errors.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(4,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
22
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(7,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
3-
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(19,14): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'Number' has no compatible call signatures.
3+
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(19,14): error TS2735: Cannot invoke expression `y`, which is a property and has the type `Number` which has no compatible call signature. Did you mean `d.y`
44
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(26,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
55
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(29,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
6-
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(41,14): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
6+
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(41,14): error TS2735: Cannot invoke expression `y`, which is a property and has the type `String` which has no compatible call signature. Did you mean `d.y`
77

88

99
==== tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts (6 errors) ====
@@ -31,7 +31,7 @@ tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIn
3131
r.y = 4;
3232
var r6 = d.y(); // error
3333
~~~~~
34-
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'Number' has no compatible call signatures.
34+
!!! error TS2735: Cannot invoke expression `y`, which is a property and has the type `Number` which has no compatible call signature. Did you mean `d.y`
3535

3636
}
3737

@@ -59,5 +59,5 @@ tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIn
5959
r.y = '';
6060
var r6 = d.y(); // error
6161
~~~~~
62-
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
62+
!!! error TS2735: Cannot invoke expression `y`, which is a property and has the type `String` which has no compatible call signature. Did you mean `d.y`
6363
}

tests/baselines/reference/instancePropertyInClassType.errors.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(4,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
22
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(7,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
3-
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(17,14): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'Number' has no compatible call signatures.
3+
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(17,14): error TS2735: Cannot invoke expression `y`, which is a property and has the type `Number` which has no compatible call signature. Did you mean `c.y`
44
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(24,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
55
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(27,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
6-
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(37,14): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
6+
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(37,14): error TS2735: Cannot invoke expression `y`, which is a property and has the type `String` which has no compatible call signature. Did you mean `c.y`
77

88

99
==== tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts (6 errors) ====
@@ -29,7 +29,7 @@ tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.t
2929
r.y = 4;
3030
var r6 = c.y(); // error
3131
~~~~~
32-
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'Number' has no compatible call signatures.
32+
!!! error TS2735: Cannot invoke expression `y`, which is a property and has the type `Number` which has no compatible call signature. Did you mean `c.y`
3333

3434
}
3535

@@ -55,5 +55,5 @@ tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.t
5555
r.y = '';
5656
var r6 = c.y(); // error
5757
~~~~~
58-
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
58+
!!! error TS2735: Cannot invoke expression `y`, which is a property and has the type `String` which has no compatible call signature. Did you mean `c.y`
5959
}

0 commit comments

Comments
 (0)