Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
recommend set if el is on RHS of assignment else get
  • Loading branch information
collin5 committed Apr 30, 2019
commit 5256ff74457ce6a618fcd750cc46d69c4c97ddc0
40 changes: 25 additions & 15 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10117,9 +10117,9 @@ namespace ts {
}
}
else {
const suggestions = getSuggestionsForNonexistentIndexSignature(objectType);
if (suggestions) {
error(accessExpression, Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature_Did_you_mean_to_call_1, typeToString(objectType), suggestions);
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));
Expand Down Expand Up @@ -20192,23 +20192,33 @@ namespace ts {
return suggestion && symbolName(suggestion);
}

function getSuggestionsForNonexistentIndexSignature(objectType: Type): string | undefined {
let suggestions: string | undefined;
const props = [
getPropertyOfObjectType(objectType, <__String>"get"),
getPropertyOfObjectType(objectType, <__String>"set")
];

for (const prop of props) {
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) === 1 && typeToString(getTypeAtPosition(s, 0)) === "string") {
const suggestion = symbolToString(objectType.symbol) + "." + symbolToString(prop);
suggestions = (!suggestions) ? suggestion : suggestions.concat(" or " + suggestion);
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;
}
return suggestions;
else {
suggestion += "." + suggestedMethod;
}

return suggestion;
}

/**
Expand Down
10 changes: 10 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand Down