切换语言为:繁体

2024年写 TypeScript 必须改掉的 10 个坏习惯

  • 爱糖宝
  • 2024-10-17
  • 2033
  • 0
  • 0

在过去的几年里,TypeScript 已经逐渐成为了前端开发的首选语言,尤其是那些追求更高代码质量和类型安全的开发者。不过,正如所有编程语言一样,随着时间的推移和技术的进步,我们的编程习惯也应该与时俱进。

👋 你有没有想过,自己在写 TypeScript 时是否养成了一些“坏习惯”?

随着 TypeScript 生态系统的进一步成熟,有些你以前觉得合理的做法,现在可能不太合理。接下来,我将分享10 个常见的 TypeScript 坏习惯,并告诉你如何改进它们,确保你的代码更健壮、性能更高、并且更加易于维护。

1. 不使用 strict 模式

当开发者为了减少“麻烦”而禁用 TypeScript 的 strict 模式时,往往是在给自己埋雷。💣

为什么不好?

strict 模式通过强制进行更严格的类型检查,帮助我们避免潜在的错误。如果你关掉它,TypeScript 就变得更像是 JavaScript,失去了静态类型带来的种种好处。短期内你可能会觉得更自由,但未来的重构和维护将变得更加棘手。

怎么改进?

在 tsconfig.json 中启用 strict 模式,这样你的代码在未来的迭代中会更加稳健:

{
  "compilerOptions": {
    "strict": true
  }
}

2. 依赖 any 类型

any 可能是 TypeScript 中最具“争议”的类型之一,因为它违背了我们使用 TypeScript 的初衷:类型安全

为什么不好?

any 让 TypeScript 失去意义。它让代码回归到“JavaScript 模式”,绕过了类型检查,最终可能导致各种运行时错误。

怎么改进?

使用 unknown 替代 any,并在实际使用前对类型进行检查。unknown 更安全,因为它不会自动允许任何操作:

let data: unknown;

if (typeof data === "string") {
  console.log(data.toUpperCase());
}

3. 过度使用类型断言

你是否经常用 as 关键字来“消除”编译错误?🙈 这种做法短期内看似有效,但可能会隐藏更多问题。

为什么不好?

类型断言会绕过 TypeScript 的安全机制,告诉编译器“别管了,我知道自己在做什么”。问题是,当你其实并不完全确定时,它会导致难以追踪的运行时错误。

怎么改进?

减少类型断言,使用类型保护函数代替:

function isString(value: unknown): value is string {
  return typeof value === 'string';
}

if (isString(data)) {
  console.log(data.toUpperCase());
}

4. 忽视联合类型和交叉类型

联合类型 (|) 和交叉类型 (&) 是 TypeScript 中极其强大的工具,但它们经常被忽视。🚫

为什么不好?

没有联合和交叉类型,代码容易变得冗长而难以维护。你可能会写大量的冗余代码,而这些类型可以帮你更简洁地表达逻辑。

怎么改进?

使用联合类型来处理不同情况,交叉类型来组合多个类型:

type Admin = { isAdmin: true; privileges: string[] };
type User = { isAdmin: false; email: string };

type Person = Admin | User;

function logUser(person: Person) {
  if (person.isAdmin) {
    console.log(person.privileges);
  } else {
    console.log(person.email);
  }
}

5. 使用非特定的返回类型

不为函数指定精确的返回类型,可能会让使用者摸不着头脑。🤔

为什么不好?

模糊的返回类型增加了代码的不确定性,调试难度也会增加。你失去了静态类型的优势,最终使代码变得不可靠。

怎么改进?

始终为函数指定明确的返回类型,哪怕它是一个联合类型:

function fetchData(): Promise<{ id: number; name: string }> {
  return fetch("/data").then(response => response.json());
}

6. 忽视 null 和 undefined

一些开发者在处理 null 和 undefined 时掉以轻心,结果导致一堆潜在的运行时错误。

为什么不好?

JavaScript 允许变量为 null 或 undefined,TypeScript 也有相应的工具帮助处理这些值。如果忽视它们,代码可能会在运行时崩溃。

怎么改进?

使用可选链 (?.) 和空值合并操作符 (??) 处理 null 和 undefined

const name = user?.profile?.name ?? "Guest";

7. 过度使用 Enums

在 TypeScript 中,Enums 有时会被滥用。尽管它们有其应用场景,但并不总是必要。

为什么不好?

Enums 会增加复杂性,尤其是在简单常量足够的情况下。

怎么改进?

考虑用 const 或字面量类型来替代枚举:

type Role = "Admin" | "User" | "Guest";

let userRole: Role = "Admin";

8. 不使用 readonly

如果不使用 readonly 来防止对象或数组的意外修改,代码中的副作用将难以控制。

为什么不好?

可变性会导致对象在不经意间被修改,造成难以调试的问题。

怎么改进?

尽可能使用 readonly 来确保不变性:

const data: readonly number[] = [1, 2, 3];

9. 忽视自定义类型保护

依赖隐式类型检查而非明确的类型保护,可能导致你错过一些重要的类型问题。

为什么不好?

没有自定义类型保护,你可能会在运行时错过一些类型错误,最终导致不可预期的行为。

怎么改进?

编写明确的类型保护函数:

function isUser(user: any): user is User {
  return typeof user.email === "string";
}

10. 没有充分利用 unknown 类型

许多开发者默认使用 any 来处理未知类型,其实 unknown 是一个更好的选择。

为什么不好?

any 禁用了类型检查,而这正是使用 TypeScript 的初衷。unknown 则要求你在使用前对类型进行明确的验证。

怎么改进?

用 unknown 代替 any,并在使用前进行类型缩小:

let input: unknown;

if (typeof input === "string") {
  console.log(input.toUpperCase());
}

总结

2024 年,是时候告别这些坏习惯了!通过启用 strict 模式、避免使用 any、掌握联合和交叉类型等高级特性,你的 TypeScript 代码将变得更强大、更灵活、更具维护性。希望这些建议能够帮助你在 TypeScript 之路上走得更远,写出更加优雅的代码!✨


0条评论

您的电子邮件等信息不会被公开,以下所有项均必填

OK! You can skip this field.