-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Description
Search Terms
newLocal, Extract to constant in enclosing scope
Suggestion
When performing “Extract to constant in enclosing scope”, if the expression being extracted is a PropertyAccessExpression
, I think it would be great if TypeScript used the expression’s name
instead of "newLocal"
, if the name would not clash with other symbols in the scope or keywords.
My suggestion summarized as a patch:
diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts
index 30dcaeaebf..c3b57c61b0 100644
--- a/src/services/refactors/extractSymbol.ts
+++ b/src/services/refactors/extractSymbol.ts
@@ -1009,7 +1009,9 @@ namespace ts.refactor.extractSymbol {
// Make a unique name for the extracted variable
const file = scope.getSourceFile();
- const localNameText = getUniqueName(isClassLike(scope) ? "newProperty" : "newLocal", file);
+ const localNameText = isPropertyAccessExpression(node) && !isClassLike(scope) && !checker.resolveName(node.name.text, node, SymbolFlags.Value, false) && !isPrivateIdentifier(node.name) && !isKeyword(node.name.originalKeywordKind!)
+ ? node.name.text
+ : getUniqueName(isClassLike(scope) ? "newProperty" : "newLocal", file);
const isJS = isInJSFile(scope);
let variableType = isJS || !checker.isContextSensitive(node)
If this sounds good, I’m happy to come up with a proper PR and submit it. Would love to try contributing :).
Use Cases
This would save me a lot of time when I extract stuff to constant (I do this a lot). Without this feature I would have to:
-
Copy the name before performing the refactoring, so that I could paste it into the rename box.
-
Sometimes I forgot to copy before extracting. I had to type the name manually.
-
That name may be long and the rename box doesn’t provide auto-completions… I had to dismiss the rename box, copy the name, and come back to the rename box.
Examples
Text version
function get(options: { url: string }) {
return fetch(options.url).then(r => r.json())
// ^^^^^^^^^^^
// Extract to constant in enclosing scope
}
Current behavior: The variable name is always newLocal
.
function get(options: { url: string }) {
const newLocal = options.url;
return fetch(newLocal).then(r => r.json())
}
Suggested behavior: The variable name is url
.
function get(options: { url: string }) {
const url = options.url;
return fetch(url).then(r => r.json())
}
Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
- This feature would agree with the rest of TypeScript's Design Goals.