mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Better errors for indexing gettable/settable values (#26446)
* give suggestions when index signature given * add tests for noImplicitAny indexing on Object * remove comments regarding error messages * recommend set if el is on RHS of assignment else get * add new baseline tests
This commit is contained in:
committed by
Ryan Cavanaugh
parent
3ce3cde493
commit
7016d45447
+36
-1
@@ -10117,7 +10117,13 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(accessExpression, Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature, typeToString(objectType));
|
||||
const suggestion = getSuggestionForNonexistentIndexSignature(objectType, accessExpression);
|
||||
if (suggestion !== undefined) {
|
||||
error(accessExpression, Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature_Did_you_mean_to_call_1, typeToString(objectType), suggestion);
|
||||
}
|
||||
else {
|
||||
error(accessExpression, Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature, typeToString(objectType));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20186,6 +20192,35 @@ namespace ts {
|
||||
return suggestion && symbolName(suggestion);
|
||||
}
|
||||
|
||||
function getSuggestionForNonexistentIndexSignature(objectType: Type, expr: ElementAccessExpression): string | undefined {
|
||||
// check if object type has setter or getter
|
||||
const hasProp = (name: "set" | "get", argCount = 1) => {
|
||||
const prop = getPropertyOfObjectType(objectType, <__String>name);
|
||||
if (prop) {
|
||||
const s = getSingleCallSignature(getTypeOfSymbol(prop));
|
||||
if (s && getMinArgumentCount(s) === argCount && typeToString(getTypeAtPosition(s, 0)) === "string") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const suggestedMethod = isAssignmentTarget(expr) ? "set" : "get";
|
||||
if (!hasProp(suggestedMethod)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let suggestion = tryGetPropertyAccessOrIdentifierToString(expr);
|
||||
if (suggestion === undefined) {
|
||||
suggestion = suggestedMethod;
|
||||
}
|
||||
else {
|
||||
suggestion += "." + suggestedMethod;
|
||||
}
|
||||
|
||||
return suggestion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a name and a list of symbols whose names are *not* equal to the name, return a spelling suggestion if there is one that is close enough.
|
||||
* Names less than length 3 only check for case-insensitive equality, not levenshtein distance.
|
||||
|
||||
@@ -4272,7 +4272,10 @@
|
||||
"category": "Error",
|
||||
"code": 7051
|
||||
},
|
||||
|
||||
"Element implicitly has an 'any' type because type '{0}' has no index signature. Did you mean to call '{1}' ?": {
|
||||
"category": "Error",
|
||||
"code": 7052
|
||||
},
|
||||
"You cannot rename this element.": {
|
||||
"category": "Error",
|
||||
"code": 8000
|
||||
|
||||
@@ -3960,6 +3960,16 @@ namespace ts {
|
||||
return isPropertyAccessExpression(node) && isEntityNameExpression(node.expression);
|
||||
}
|
||||
|
||||
export function tryGetPropertyAccessOrIdentifierToString(expr: Expression): string | undefined {
|
||||
if (isPropertyAccessExpression(expr)) {
|
||||
return tryGetPropertyAccessOrIdentifierToString(expr.expression) + "." + expr.name;
|
||||
}
|
||||
if (isIdentifier(expr)) {
|
||||
return unescapeLeadingUnderscores(expr.escapedText);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function isPrototypeAccess(node: Node): node is PropertyAccessExpression {
|
||||
return isPropertyAccessExpression(node) && node.name.escapedText === "prototype";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user