重构 TypeScript
最后修改时间:2023 年 9 月 28 日所需插件:
Javascript and TypeScript - 该插件仅在 IntelliJ IDEA Ultimate 中可用,默认情况下启用。
重构意味着更新源代码而不改变应用程序的行为。重构可以帮助您保持代码可靠、干燥且易于维护。
移动重构
除了移动文件和文件夹之外,IntelliJ IDEA 还允许您移动 TypeScript 顶级符号。Move Symbol Refactoring适用于 ES6 模块中的类、函数和变量。
移动类、函数或变量
选择要移动的符号。
按或选择重构 | 从主菜单或选择的上下文菜单移动。或者,选择重构 | 重构此或按,然后从列表中选择“移动” 。F6CtrlAltShift0T
“移动模块成员”对话框打开。
指定目标文件并选择要移动的成员。
默认情况下,IntelliJ IDEA 会自动将成员的可见性提高到所需的级别。如果要保持可见性级别不变,请在“可见性”中单击“原样”。
拉动类成员重构
“上拉类成员”重构将类方法在类层次结构中向上移动 - 从当前类到超类或其实现的接口。
假设您有一个AccountingDepartment扩展抽象类Department并实现接口的类ReportingDepartment。
abstract class Department {
constructor(public name: string) {
}
printName(): void {
console.log("Department name: " + this.name);
}
}
interface ReportingDepartment {
generateReports(): void
}
class AccountingDepartment extends Department implements ReportingDepartment {
constructor() {
super("Accounting and Auditing");
}
printMeeting(): void {
console.log("The Accounting Department meets each Monday at 10 a.m");
}
generateReports(): void {
console.log("Generating accounting reports...");
}
}示例 1:将类方法移至超类
在此示例中,该PrintMeeting()方法从AccountingDepartment移至Department。
abstract class Department {
constructor(public name: string) {
}
printName(): void {
console.log("Department name: " + this.name);
}
printMeeting(): void {
console.log("The Accounting Department meets each Monday at 10 a.m");
}
}
interface ReportingDepartment {
generateReports(): void
}
class AccountingDepartment extends Department implements ReportingDepartment {
constructor() {
super("Accounting and Auditing");
}
generateReports(): void {
console.log("Generating accounting reports...");
}
}
示例 2:将类方法移至接口
在此示例中,PrintMeeting()方法从类复制AccountingDepartment到ReportingDepartment接口。
abstract class Department {
constructor(public name: string) {
}
printName(): void {
console.log("Department name: " + this.name);
}
}
interface ReportingDepartment {
generateReports(): void
printMeeting(): void
}
class AccountingDepartment extends Department implements ReportingDepartment {
constructor() {
super("Accounting and Auditing");
}
printMeeting(): void {
console.log("The Accounting Department meets each Monday at 10 a.m");
}
generateReports(): void {
console.log("Generating accounting reports...");
}
}将类的方法移至超类或接口
将插入符号放在类中要从中拉出成员的任意位置。
选择重构 | 从主菜单或上下文菜单中拉出成员。将打开“拉出成员”对话框。
从列表中,选择要将方法移动到的超类或接口。
要拉出方法,请在“要拉出的成员”列表中选中该方法旁边的复选框。如果适用,请选中要移动的方法旁边的“制作摘要”复选框。
重命名重构
除了在任何语言的上下文中可用的重命名文件和文件夹之外,您还可以重命名类、方法、变量、参数和字段。IntelliJ IDEA 更改其声明中的符号名称以及默认情况下其在当前项目中的所有用法。

“重命名”重构是就地执行的,但您可以按在“重命名”对话框中配置重构范围。ShiftF6
要默认打开该对话框,请打开“设置”对话框 ( ),然后转至编辑器 | 代码编辑,然后在“指定重构选项”区域中选择“在模式对话框中”选项。CtrlAlt0S
提示
在“重命名”对话框中选中“搜索动态引用”复选框后,该对话框将默认打开,直到您清除该复选框。
在编辑器中,选择要重命名的类、方法、变量或字段,然后按或选择Refactor | 从上下文菜单或主菜单重命名。ShiftF6
在画布字段中,指定符号的新名称。输入名称或从列表中选择合适的名称。
可选:
单击
突出显示的符号旁边的 ,打开“同时在弹出窗口中重命名”,然后选择“在注释和字符串中搜索”和“搜索文本出现”复选框,以重命名注释、字符串文字和文本中符号的用法。
提示
重命名参数时,弹出窗口中的“同时重命名”
不可用。要指定其他选项,请再次打开“重命名”对话框。ShiftF6
可选:
要打开包含更多选项的重命名对话框,请再按一次。ShiftF6
选中“在注释和字符串中搜索”复选框可重命名注释、文档注释和字符串文字中符号的用法。
选中“搜索文本出现”复选框可重命名 HTML 和项目中包含的其他文件中的文本中的匹配符号。
选中“在 JavaScript 文件中搜索”复选框以重命名生成的 JavaScript 代码中符号的用法。
选择搜索动态引用复选框以重命名符号的动态用法。
提示
如果您选中“搜索动态引用”复选框,则默认情况下将打开该对话框,直到您清除它为止。
请注意,在重构中包含动态用法可能会导致错误的重命名,如下例所示。这里的
targetinconsole.log(e.target)可以改为myTarget因为e有类型any,也就是说也可以是myInt。重命名前动态使用重命名interface myInt { target: string } function onClick(e: any) { console.log(e.target); }interface myInt { myTarget: string } function onClick(e: any) { console.log(e.myTarget); }
为了避免错误重命名,请在应用更改之前预览更改。
默认情况下,在“重构预览”工具窗口中,符号的所有动态用法都标记为已排除,并分组在“代码中对 <symbol> 的动态引用”节点下。要将重构应用于用法,请从其上下文菜单中选择“包含” 。

保持类名称和包含文件的名称一致
当您重命名类时,如果文件具有相同的名称,IntelliJ IDEA 还会建议重命名该文件。如果您接受建议,IntelliJ IDEA 会在其他文件的导入语句中更新此文件的名称。
如果您拒绝此建议,您可以稍后使用“重命名文件...”意图操作重命名该文件。如果您刚刚创建了一个新文件,但在开始在其中键入类或接口时想出了一个更好的名称,那么这非常有用。
另一个意图操作建议将类移动到具有相应名称的新文件中。建议文件名的格式由从代码样式:JavaScript页面上的文件名约定列表中选择的样式确定。
保持文件名与对应类的名称一致
将插入符号放在类的名称处,然后按。AltEnter
从意图列表中,选择将文件重命名为 <class_name.ts> 以匹配类名称或将类 <class_name> 移动到文件 <class_name.ts>。

提取/引入重构
IntelliJ IDEA 提供了各种Extract重构来引入参数、变量、常量、字段、方法和函数。要运行任何这些重构,请选择要重构的表达式,然后选择“重构”|“重构”。<目标>。您可以选择整个表达式或将插入符号放置在其中的任意位置,IntelliJ IDEA 将帮助您进行选择。
参数介绍
使用引入参数重构将函数调用中的表达式替换为参数。IntelliJ IDEA 将相应地更新函数的声明和调用。新参数的默认值可以在函数体内初始化或通过函数调用传递。
假设您有一段"Hello, "在函数中硬编码的代码greeter()。
function greeter(firstName : String, lastName : String) {
return "Hello, " + firstName + " " + lastName;
}
document.body.innerHTML = greeter("Jane","User");"Hello, "用greeting参数替换此硬编码。新greeting参数可以作为可选参数或根据需要提取。示例 1:提取可选参数
提取新参数greeting作为可选参数。greeter()新参数被添加到使用函数默认参数语法的定义中。的调用greeter()没有改变。
function greeter(firstName : String, lastName : String, greeting = "Hello, ") {
return greeting + firstName + " " + lastName;
}
document.body.innerHTML = greeter("Jane","User");示例2:提取所需参数
greeting在该示例中,提取新参数作为必需参数。所以相应的函数调用(document.body.innerHTML = greeter(user);也相应改变。
function greeter(firstName : String, lastName : String, greeting: string) {
return greeting + firstName + " " + lastName;
}
document.body.innerHTML = greeter("Jane", "User", "Hello, ");引入一个参数
在编辑器中,将插入符号放在要转换为参数的表达式内,然后按或选择Refactor | 从上下文菜单中引入参数。CtrlAlt0P
或者,执行以下操作之一:
按并选择引入参数。CtrlAltShift0T
转到重构 | 摘录| 范围。
如果在当前插入符号位置检测到多个表达式,请从“表达式”列表中选择所需的表达式。

如果找到多个所选表达式,请从“找到多个匹配项”列表中选择“仅替换此匹配项”或“替换所有匹配项”。最后,出现配置重构的弹出窗口。

选择“生成 JSDoc”以生成JSDoc注释块。如果您需要指定自定义默认参数值,这可能会有所帮助。
选择新参数的初始化位置并指定其默认值(如果适用):
如果选中可选参数复选框,则参数将使用函数体中的默认值进行初始化。
如果清除可选参数复选框,则默认参数值将通过现有函数调用传递。所有函数调用都将根据新函数签名进行更改,并且参数初始化将添加到函数体中。
最初,IntelliJ IDEA 接受调用重构的表达式作为默认值。大多数情况下,您不需要更改它。如果仍然需要,请在 JSDoc 注释中以 格式指定另一个默认值
@param <parameter name> - <default value>。从TypeScript 官方网站了解有关可选参数和默认参数的更多信息。
通过在列表中双击建议的参数名称之一来接受它,或者在带有红色画布的字段中指定自定义名称。准备好后按下。Enter

选择重构模式
您可以如上所述直接在编辑器中(在就地模式下)提取参数,或使用“引入参数”对话框。这两种方法很相似,区别如下:
引入变量
使用引入变量重构将表达式替换为函数作用域变量 (var)、块作用域变量 (let)或块作用域常量 (const)。这种重构使您的源代码更易于阅读和维护。它还可以帮助您避免使用硬编码常量,而不对其值或用途进行任何解释。
function Multiplication(a : number, b : number) {
let d = (a + b) * (a + b);
return d;
}
var e = Multiplication(4, 6);function Multiplication(a : number, b : number) {
let c = a + b;
let d = (c) * (c);
return d;
}
var e = Multiplication(4, 6);引入一个变量
在编辑器中,选择要转换为变量的表达式,然后按并选择Refactor | 从上下文菜单中引入变量。CtrlAlt0V
或者,执行以下操作之一:
按并选择引入变量。CtrlAltShift0T
转到重构 | 摘录| 多变的。
如果在当前插入符号位置检测到多个表达式,请从“表达式”列表中选择所需的表达式。

如果找到多个所选表达式,请从“找到多个匹配项”列表中选择“仅替换此匹配项”或“替换所有匹配项”。

最后,出现配置重构的弹出窗口。
从列表中,选择要在新变量声明中使用的语句:

通过在列表中双击建议的参数名称之一来接受它,或者在带有红色画布的字段中指定自定义名称。准备好后按下。Enter
选择重构模式
您可以如上所述在编辑器中直接提取变量(在就地模式下),或者使用“引入变量”对话框。默认情况下,IntelliJ IDEA 在就地模式下运行引入变量重构。要使用“提取变量”对话框,请打开“设置”对话框 ( ),然后转至编辑器 | 代码编辑,然后选择“重构”区域中的“在模式对话框中”选项。CtrlAlt0S
引入常数
使用引入常量重构将表达式替换为常量。这种重构使您的源代码更易于阅读和维护。它还可以帮助您避免使用硬编码常量,而不对其值或用途进行任何解释。

假设您有一段硬编码的代码片段Department name:。
printName(): void {
console.log("Department name: " + this.name); }通过引入常量重构,您可以Department name用常量替换硬编码。提取的常量的范围取决于声明新常量的上下文(在封闭方法内部、作为类的字段或在任何类外部)。
示例 1:引入的常量 departmentName 在封闭方法 printName() 内声明
printName(): void {
console.log("Department name: " + this.name);
}printName(): void {
const departmentName = "Department name: ";
console.log(departmentName + this.name);
}示例 2:引入的常量被声明为封闭类 AccountingDepartment 的 _departmentName 字段
class AccountingDepartment extends Department implements ReportingDepartment {
name: string;
printName(): void {
console.log("Department name: " + this.name);
}
}class AccountingDepartment extends Department implements ReportingDepartment {
name: string;
private readonly _departmentName = "Department name: ";
printName(): void {
console.log(this._departmentName + this.name);
}
}示例3:引入的常量departmentName在任何类之外声明
class AccountingDepartment extends Department implements ReportingDepartment {
name: string;
printName(): void {
console.log("Department name: " + this.name);
}
}abstract class Department {...}
const deparmentName = "Department name: ";
class AccountingDepartment extends Department implements ReportingDepartment {...}引入一个常数
在编辑器中,选择要转换为常量的表达式,然后按或选择Refactor | 从上下文菜单中引入常量。CtrlAlt0C
或者,执行以下操作之一:
按并选择引入常数。CtrlAltShift0T
转到重构 | 摘录| 持续的。

如果在当前插入符号位置检测到多个表达式,请从“表达式”列表中选择所需的表达式。

选择新常量的范围:

如果 IntelliJ IDEA 检测到多次出现该表达式,请选择是要替换所有表达式还是仅替换调用重构的表达式。

通过在列表中双击建议的参数名称之一来接受它,或者在带有红色画布的字段中指定自定义名称。准备好后按下。Enter

介绍领域
Introduce Field重构声明一个新字段并使用所选表达式对其进行初始化。原来的表达式被替换为字段的用法。
假设您有以下代码:
class Rectangle {
constructor(public height: number, public width: number) {
this.height = height;
this.width = width;
}
get area() {
return this.calcArea();
}
calcArea() {
return this.height * this.width;
}
}_calcArea。这些示例说明了初始化引入字段的三种不同方法。示例 1:引入的字段 _calcArea 在封闭方法 get Area() 中初始化
class Rectangle {
constructor(public height: number, public width: number) {
this.height = height;
this.width = width;
}
private _calcArea: number;
get area() {
this._calcArea = this.calcArea();
return this._calcArea;
}
calcArea() {
return this.height * this.width;
}
}示例2:引入的字段_calcArea在其声明中初始化
class Rectangle {
constructor(public height: number, public width: number) {
this.height = height;
this.width = width;
}
private _calcArea = this.calcArea();
get area() {
return this._calcArea;
}
calcArea() {
return this.height * this.width;
}
}