Push variable declaration into initial valuepro
Inlines a variable that is initialized with another variable into the declaration of that variable.

When a variable is initialized with a second variable, and that second variable is only used in that initialization, you can use the variable instead of the second variable and remove the indirection.
For example, here variable
can be pushed in the definition of secondVariable
:
const secondVariable = someSource();
const variable = secondVariable;
becomes
const variable = someSource();
Why is this refactoring helpful?
The refactoring helps remove unnecessary indirection. It is particularly useful for pushing destructuring into parameters and catch clauses:
function f(aParameter) {
const { variable1, variable2 } = aParameter;
doSomething(variable1, variable2);
}
becomes
function f({ variable1, variable2 }) {
doSomething(variable1, variable2);
}
What do I need to consider?
The variable type can change
When the two variable declarations have different types, and the first declaration declares several variables, the broader type needs to be used.
This means that const
can be changed into let
or var
, and let
can be changed into var
. The change to let
means that previously constant variables now can be modified, and the change to var
can change the scope of the variable.
Consider the following example:
const intermediateVariable = someSource(),
anotherVariable = anotherSource();
var aVariable = intermediateVariable;
Here, pushing up aVariable
and removing intermediateVariable
requires changing the const
to var
to support the scope of aVariable
. This refactoring changes the scope of anotherVariable
as well.
Similarly, pushing a const
variable into a function or catch clause parameter means it will become modifiable.
Exports can be affected
When one of the two variable declarations is exported, the refactoring can impact the module's exports.
For example,
export const obj = something;
const aVariable = obj;
becomes
export const aVariable = something;
This change impacts the module's exports, and you might need to update references to it inside other modules as well. If the exports are library exports, this could be a breaking change.
The execution order can change when inlining destructuring
Destructuring can have side effects when e.g., getters are invoked. When pushing up a variable into its definition, it can affect the execution order.
Here is an example:
const executed = [];
class Example {
constructor(name) {
this.name = name;
}
get field() {
executed.push(`${this.name} - field`);
return "field";
}
get innerExample() {
executed.push(`${this.name} - inner example`);
return new Example("inner");
}
}
const { innerExample: intermediateVariable, field } = new Example("outer");
const { field: innerField } = intermediateVariable;
console.log(executed); // [ 'outer - inner example', 'outer - field', 'inner - field' ]
After the refactoring, the bottom part becomes:
const { innerExample: { field: innerField }, field } = new Example("outer");
console.log(executed); // [ 'outer - inner example', 'inner - field', 'outer - field' ]
inner - field
is now added to executed
before outer - field
.
The TypeScript type can be narrowed
When the intermediate variable is part of a destructuring expression, the type information from the inlined variable is dropped. This can lead to a narrowing of the type.
const { value: intermediateVariable }: {value: "123"} = {
value: "123"
}
const aVariable: string = intermediateVariable;
becomes
const { value: aVariable }: {value: "123"} = {
value: "123"
}
// now aVariable has type "123" and not string
Configuration
- Code Assist ID (for the configuration file):
push-into-initial-value-declaration
- You can configure custom keyboard shortcuts with this code action kind:
refactor.inline.p42.push-into-initial-value-declaration