为什么 TypeScript 整洁代码不是奢侈,而是必需
每位开发者都至少遇到过这种情况:打开一个几个月前写的项目,却完全看不懂发生了什么。变量命名为 a、b、data,函数长达 200 行,类型也是随意标注。熟悉吗?
TypeScript 为我们提供了强大的工具——静态类型。但它本身并不会让代码变得整洁。你完全可以用 TypeScript 或其他任何语言写出糟糕的代码。整洁代码是一种纪律、一种风格,更是对自己和同事的尊重。
在本文中,我们将探讨如何编写易于阅读、维护和扩展的 TypeScript 整洁代码。你将了解 SOLID 原则、强类型、命名规范、接口使用等更多内容。我们开始吧!
1. 命名——代码的门面
正确命名变量、函数和类,是成功的一半。一个好的名称应该能回答以下问题:“这是什么?”或“这个函数做什么?”。
变量和常量
使用名词和 camelCase 命名法。避免使用单个字母的名称(循环除外)。
// 糟糕
const d = new Date();
const u = users.find(u => u.id === 5);
// 良好
const currentDate = new Date();
const activeUser = users.find(user => user.id === 5);
函数
函数名应以动词开头。这能立即表明正在执行的操作。
// 糟糕
function data(id: number) { ... }
// 良好
function fetchUserData(id: number): Promise<UserData> { ... }
类和接口
类使用 PascalCase 命名法,为名词。接口同样使用 PascalCase,但社区中常加前缀 I(尽管存在争议)。更好的做法是直接使用无前缀的清晰名称。
// 糟糕
interface IUser {
name: string;
}
// 良好
interface User {
name: string;
email: string;
}
2. 强类型——你最好的朋友
TypeScript 的创建目的就是让类型为你服务。除非万不得已,否则不要使用 any。每次你写 any,都是在关闭编译器的保护。
避免使用 any
// 糟糕
function process(data: any) {
return data.name;
}
// 良好
interface Item {
name: string;
price: number;
}
function process(data: Item): string {
return data.name;
}
使用联合类型和交叉类型
当变量可能接受多种类型时,使用联合类型 (|)。需要组合类型时,使用交叉类型 (&)。
type Status = 'active' | 'inactive' | 'pending';
type AdminUser = User & { role: 'admin' };
泛型——通用函数
泛型允许编写灵活代码而不丢失类型信息。
function firstElement<T>(arr: T[]): T | undefined {
return arr[0];
}
const num = firstElement([1, 2, 3]); // number
const str = firstElement(['a', 'b']); // string
3. SOLID——面向成人的原则
SOLID 原则有助于构建灵活且可维护的架构。我们以 TypeScript 为例逐一介绍。
单一职责原则 (SRP)
一个类或函数应该只有一个修改的理由。
// 糟糕:一个类做所有事
class UserService {
createUser() { ... }
sendEmail() { ... }
generateReport() { ... }
}
// 良好:分离职责
class UserCreator { ... }
class EmailService { ... }
class ReportGenerator { ... }
开闭原则 (OCP)
类应对扩展开放,对修改关闭。使用接口和继承。
里氏替换原则 (LSP)
子类应能替换基类而不改变程序行为。