拒绝 TypeScript 表明你不关心代码质量


几天前,DHH宣布在 Turbo 8放弃 TypeScript。我对此没有意见,因为我甚至不知道 Turbo 8 是什么。然而,在过去几年中,一些前端程序员试图向我兜售 "TypeScript 毫无用处,使用测试即可 "的观点。

我认为,持这种观点的人要么不关心代码质量,要么根本不知道 TypeScript 是什么。

在这里,我将解释为什么你应该使用 TypeScript。

要保持代码的可维护性,代码质量控制是一个复杂的过程。你不可能只在代码上进行 100% 的测试,也不可能只审查每个拉取请求就能确保代码的可维护性,而且除了你之外,还有其他人能在这种混乱的情况下找出问题所在。

你根本无法确保你的代码没有错误,也无法确保代码具有完美的可维护性。你只能在版本库中增加防御结构,让有错误的代码难以推送。对不良代码设置的障碍越多,代码质量就越高。

这意味着您应该使用所有方法来保护版本库中的代码:单元/e2e/集成测试、代码审查、代码分析工具和维护清晰的文档等。

TypeScript 是一款功能强大的代码分析工具;它可以检测出代码中的许多缺陷。TypeScript 编译器迫使程序员确保代码在类型级别上的正确性。David 和许多人都低估了静态类型的价值。

让我们来看看 TypeScript 能为代码质量带来哪些好处:

合约
静态类型允许在代码中定义合约:

type Participant = {
    id: string;
    name: string;
};

function sayHi(participant: Participant) {
    //...
    console.log(`Hi ${participant.name}`);
}

sayHi 函数需要一个具有精确属性和精确类型的对象,它并不关心该函数的用户将如何满足这些要求。编译器会确保类型正确。
用户可能会提供一个不符合要求的对象,并将类型转换为任意类型,但这并不是 sayHi 函数的问题。这是一种责任委托,开发人员必须理解这一重要概念,才能正确使用 TypeScript 并从中获益。

程序员必须验证任何不可信任的数据,如用户输入和其他 IO 数据,或与 JavaScript 交互的结果。在验证和设置类型后,程序员就可以将数据传递给 TypeScript 代码,并相信合同会得到遵守,因为 TypeScript 编译器已对代码进行了检查。如果程序员对类型进行了赋值,则必须确保代码在运行时是正确的。

如果您可以将项目中的非交集类型转换为除未知类型之外的任何类型,而无需运行时验证,那么您的项目很可能存在代码质量问题。
通过合约,您可以避免为每个函数编写验证以确保数据的正确性。这对性能和代码整洁度都有很大好处,代码会变得愚蠢而简单。

开发人员的经验和开发成本
有时我会用纯 JavaScript 编写代码,主要是在浏览器控制台中进行快速计算或在网页上进行数据解析。几个月前,我为 Node.js 编写了一个脚本,使用 ChatGPT 翻译本地文件。这些文件包含较长的文本,而 ChatGPT 有限制,因此需要一些时间对文本进行切片、翻译、查找 ChatGPT 结果中的错误、根据需要重新翻译,然后将切片连接起来。根据本地文件的大小,这个过程大约需要 3-5 分钟。

在这个过程中,我因为一些微不足道的类型错误浪费了一些时间,比如忘记使用 await,导致变量包含 Promise,并将"[object Promise]"写入文件,而不是翻译后的文本,或者提供了错误的对象作为函数参数。

TypeScript 可以消除诸如此类的错误。

投资未来
TypeScript 为您的代码提供了由其他工具进行分析的可能性,因为它增加了上下文。

使用 IDE,您可以重命名接口中的一个属性,而实现该接口的所有实体都会在各自的位置自动更新该属性的名称。

ChatGPT 和 Copilot 等人工智能工具可以从 TypeScript 提供的额外元信息中获益,从而改进代码分析和代码生成。分析工具可以更好地识别潜在风险代码。

静态类型和测试可以很好地互补。前端代码是高度异步的,因此覆盖所有可能的测试用例并考虑所有潜在的代码状态具有挑战性。TypeScript 迫使程序员处理一个状态可能出现的所有情况,从而提高了代码的可靠性。

类型的复杂性
DHH说

对我来说,TypeScript 阻碍了我。这不仅仅是因为它需要一个明确的编译步骤,还因为它用类型体操污染了代码,给我的开发体验带来的快乐少之又少,而且经常是相当大的痛苦。本该简单的事情变得困难,而困难的事情又变得简单。不,谢谢!

我引用这句话是因为我已经听过很多次了。

的确,有时你必须编写非繁琐的类型,才能让编译器相信你的数据是正确的。

这没什么。创建可维护的高质量代码往往需要付出艰苦的努力。

结论
TypeScript 只是一种工具,如果您只是简单地启用它,它不会自动提高代码质量。您的项目必须制定正确使用该工具的规则,并由架构师来执行这些规则。规则越严格越好。

如果在项目中禁用静态类型,就会失去许多控制代码质量的功能。

JSDoc 和 .d.ts 类型声明文件不能取代代码的静态类型。它们只是声明实体外部 API 的方法,但不能分析实体(函数、类和其他代码块)内的代码。