文章介绍了Safdar Ali在《10 Bad TypeScript Habits To Break In 2024》中列举的十种常见的TypeScript不良习惯,包括不使用严格模式、过度依赖any类型、滥用类型断言等,并给出了改进建议。这些不良习惯会影响代码质量和可维护性。
严格模式通过更严格的类型检查提高代码的健壮性。关闭严格模式会导致类型检查的松懈,增加代码出错的风险。
any类型允许变量接受任何类型的值,这实际上绕过了TypeScript的类型检查机制。过度使用any类型会使TypeScript失去其静态类型系统的优势,增加运行时错误的可能性。
联合类型和交叉类型是TypeScript中强大的类型系统特性,能够更精确地描述复杂的数据结构。忽视这些类型会导致代码的冗长和类型定义的不精确。
函数返回类型的不明确会导致代码的可读性和可维护性下降。明确的返回类型有助于开发者更好地理解函数的预期输出。
JavaScript中null和undefined的存在是常见的错误来源。忽视它们会导致运行时错误。
在某些情况下,枚举可能被过度用于简单的常量值,而其他类型(如const或字面量联合类型)可能更为合适。
unknown类型是any类型的更安全的替代品,它要求在使用值之前进行类型检查。
作者:@Safdar Ali
原文:https://dev.to/safdarali/10-bad-typescript-habits-to-break-in-2024-2p54
背景
TypeScript 作为一种在 JavaScript 基础上增加了静态类型系统的编程语言,近年来在开发者社区中越来越受欢迎。然而,随着 TypeScript 的不断发展,一些过去被认为是最佳实践的习惯可能已经变得过时或不再适用。Safdar Ali 在其文章《10 Bad TypeScript Habits To Break In 2024》中列举了十种常见的 TypeScript 不良习惯,并提供了改进建议。
【第3359期】没人告诉你的一件关于 TypeScript 的事
要点
文章指出了十种常见的 TypeScript 不良习惯,包括不使用严格模式、过度依赖
any
类型、滥用类型断言、忽视联合和交叉类型、使用非特定返回类型、忽略
null
和
undefined
、过度使用枚举、不利用
readonly
、忽视自定义类型守卫以及不充分利用
unknown
类型。
分析
一、 不使用严格模式 (strict Mode)
严格模式(strict mode)是 TypeScript 中的一项重要功能,它通过启用一系列更严格的类型检查来提高代码的健壮性。关闭严格模式会导致类型检查的松懈,增加代码出错的风险。
问题:许多开发者为了避免处理更严格的类型检查,会禁用 TypeScript 的严格模式。
弊端:关闭严格模式会降低 TypeScript 类型安全的有效性,可能导致意外错误,并增加未来重构的难度。
解决方案:在 tsconfig.json 文件中启用严格模式,强制执行更完善的类型检查,确保代码更加健壮。
{
"compilerOptions": {
"strict": true
}
}
二、 过度依赖 any 类型
any
类型允许变量接受任何类型的值,这实际上绕过了 TypeScript 的类型检查机制。过度使用
any
类型会使 TypeScript 失去其静态类型系统的优势,增加运行时错误的可能性。
问题:开发者在不想思考正确类型时,经常使用 any 类型作为快速解决方案。
弊端:使用 any 类型会绕过 TypeScript 的所有类型检查,使其本质上又变回了 JavaScript。这可能导致运行时错误,因为 TypeScript 无法在开发过程中帮助捕捉错误。
解决方案:使用更具体的类型,例如 unknown,或者更好的是,为数据定义适当的类型。unknown 类型比 any 更安全,因为它强制在使用值之前进行类型检查。
let data: unknown;
if (typeof data === "string") {
console.log(data.toUpperCase());
}
三、 随意使用类型断言
类型断言(type assertion)允许开发者强制 TypeScript 将一个值视为特定类型,即使该值可能不是该类型。滥用类型断言会导致代码的不安全性,因为 TypeScript 无法在编译时捕获这些潜在的错误。
问题:类型断言(as 关键字)可能会被过度使用,尤其是在开发者不确定类型并希望抑制 TypeScript 错误时。
弊端:类型断言可能导致不安全的代码,因为它们告诉 TypeScript 将值视为特定类型,即使它可能不是。如果值不是预期的类型,则可能导致运行时问题。
解决方案:限制类型断言的使用。可以使用类型守卫,它允许在使用值之前安全地检查和推断类型。
function isString(value: unknown): value is string {
return typeof value === 'string';
}
if (isString(data)) {
console.log(data.toUpperCase());
}
四、 忽视联合类型和交叉类型
联合类型(union types)和交叉类型(intersection types)是 TypeScript 中强大的类型系统特性,能够更精确地描述复杂的数据结构。忽视这些类型会导致代码的冗长和类型定义的不精确。
问题:一些开发者即使在联合类型 (
|
) 和交叉类型 (
&
) 能使代码更具表现力和精确性的情况下,也避免使用它们。
弊端:不使用联合类型和交叉类型会导致代码过于冗长,并且可能会错过 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);
}
}
五、 使用非特定返回类型
函数返回类型的不明确会导致代码的可读性和可维护性下降。明确的返回类型有助于开发者更好地理解函数的预期输出,减少调试的难度。
问题:函数的返回类型通常是 any、object 或其他非特定类型,这使得函数的使用者需要自行弄清楚预期结果。