Skip to content

Clarify error message when an accessor is invoked. #27897

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 52 additions & 5 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,17 @@ namespace ts {
const parsed = getParseTreeNode(node, isFunctionLike);
return parsed ? isImplementationOfOverload(parsed) : undefined;
},
getImmediateAliasedSymbol,
getImmediateAliasedSymbol: symbol => {
Debug.assert((symbol.flags & SymbolFlags.Alias) !== 0, "Should only get Alias here.");
const links = getSymbolLinks(symbol);
if (!links.immediateTarget) {
const node = getDeclarationOfAliasSymbol(symbol);
if (!node) return Debug.fail();
links.immediateTarget = getTargetOfAliasDeclaration(node, /*dontRecursivelyResolve*/ true);
}

return links.immediateTarget;
},
getAliasedSymbol: resolveAlias,
getEmitResolver,
getExportsOfModule: getExportsOfModuleAsArray,
Expand Down Expand Up @@ -20796,13 +20806,47 @@ namespace ts {
}
else {
let relatedInformation: DiagnosticRelatedInformation | undefined;
let propertyName: string | undefined;
let propertyAccessorText: string | undefined;
if (node.arguments.length === 1) {
const text = getSourceFileOfNode(node).text;
if (isLineBreak(text.charCodeAt(skipTrivia(text, node.expression.end, /* stopAfterLineBreak */ true) - 1))) {
relatedInformation = createDiagnosticForNode(node.expression, Diagnostics.It_is_highly_likely_that_you_are_missing_a_semicolon);
}
}
invocationError(node, apparentType, SignatureKind.Call, relatedInformation);
else if (node.expression.kind === SyntaxKind.PropertyAccessExpression) {
const propertyAccess = node.expression as PropertyAccessExpression;
const symbol = getSymbolOfEntityNameOrPropertyAccessExpression(propertyAccess);

// Handle union types with non-function-like signatures.
if (symbol) {
const links = getSymbolLinks(symbol);
const isObjectUnionOrIntersection = links && links.type && (
(links.type.flags & (TypeFlags.Union | TypeFlags.Intersection | TypeFlags.Object)) !== 0
) || false;

let invokable = isObjectUnionOrIntersection;
if (isObjectUnionOrIntersection) {
if (links && links.type && (links.type.flags & TypeFlags.Object)) {
const resolvedType = links.type as ObjectType;
invokable = (resolvedType.callSignatures && resolvedType.callSignatures.length !== 0) || false;
}
else {
const resolvedType = links.type as UnionOrIntersectionType;
invokable = every(resolvedType.types, ty => (ty as ResolvedType).callSignatures && (ty as ResolvedType).callSignatures.length !== 0);
}
}

if (!invokable) {
const file = getSourceFileOfNode(node);

propertyName = propertyAccess.name.escapedText.toString();
propertyAccessorText = createPrinter().printNode(EmitHint.Expression, propertyAccess, file);
}
}
}

invocationError(node, apparentType, SignatureKind.Call, relatedInformation, propertyName, propertyAccessorText);
}
return resolveErrorCall(node);
}
Expand Down Expand Up @@ -20972,11 +21016,14 @@ namespace ts {
return true;
}

function invocationError(node: Node, apparentType: Type, kind: SignatureKind, relatedInformation?: DiagnosticRelatedInformation) {
function invocationError(node: Node, apparentType: Type, kind: SignatureKind, relatedInformation?: DiagnosticRelatedInformation, propertyName?: string, didYouMean?: string) {
const diagnostic = error(node, (kind === SignatureKind.Call ?
Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures :
(propertyName === undefined ?
Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures :
Diagnostics.Cannot_invoke_expression_1_which_is_a_property_and_has_the_type_0_which_has_no_compatible_call_signature_Did_you_mean_2
) :
Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature
), typeToString(apparentType));
), typeToString(apparentType), propertyName, didYouMean);
invocationErrorRecovery(apparentType, kind, relatedInformation ? addRelatedInfo(diagnostic, relatedInformation) : diagnostic);
}

Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2585,6 +2585,10 @@
"category": "Error",
"code": 2749
},
"Cannot invoke expression `{1}`, which is a property and has the type `{0}` which has no compatible call signature. Did you mean `{2}`": {
"category": "Error",
"code": 2750
},

"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(4,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(7,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
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.
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(19,14): error TS2750: Cannot invoke expression `y`, which is a property and has the type `Number` which has no compatible call signature. Did you mean `d.y`
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(26,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(29,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
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.
tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIntoClassType.ts(41,14): error TS2750: Cannot invoke expression `y`, which is a property and has the type `String` which has no compatible call signature. Did you mean `d.y`


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

}

Expand Down Expand Up @@ -59,5 +59,5 @@ tests/cases/conformance/classes/members/classTypes/instancePropertiesInheritedIn
r.y = '';
var r6 = d.y(); // error
~~~~~
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
!!! error TS2750: Cannot invoke expression `y`, which is a property and has the type `String` which has no compatible call signature. Did you mean `d.y`
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(4,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(7,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
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.
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(17,14): error TS2750: Cannot invoke expression `y`, which is a property and has the type `Number` which has no compatible call signature. Did you mean `c.y`
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(24,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(27,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
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.
tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.ts(37,14): error TS2750: Cannot invoke expression `y`, which is a property and has the type `String` which has no compatible call signature. Did you mean `c.y`


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

}

Expand All @@ -55,5 +55,5 @@ tests/cases/conformance/classes/members/classTypes/instancePropertyInClassType.t
r.y = '';
var r6 = c.y(); // error
~~~~~
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.
!!! error TS2750: Cannot invoke expression `y`, which is a property and has the type `String` which has no compatible call signature. Did you mean `c.y`
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
tests/cases/compiler/file1.ts(2,16): error TS2748: Cannot access ambient const enums when the '--isolatedModules' flag is provided.
tests/cases/compiler/file1.ts(2,16): error TS2750: Cannot access ambient const enums when the '--isolatedModules' flag is provided.


==== tests/cases/compiler/file1.ts (1 errors) ====
declare const enum E { X = 1}
export var y = E.X;
~
!!! error TS2748: Cannot access ambient const enums when the '--isolatedModules' flag is provided.
!!! error TS2750: Cannot access ambient const enums when the '--isolatedModules' flag is provided.