在开始之前,我希望读者知道我是TypeScript 的忠实粉丝。我的前端React 项目和各种后端Node 工作主要使用TypeScript。我同意这个想法,但我有一些问题,所以我想在本文中讨论它们。到目前为止,我已经使用TypeScript 编写代码至少三年了,并且参与了无数的项目。所以TypeScript 肯定走在正确的轨道上或者满足了某些需求。
TypeScript 克服了一些难以逾越的障碍,成为前端编程的主流选择。 TypeScript 在本文列出的最流行编程语言中排名第7。
各种规模的软件团队都应该遵循这些实践,无论他们是否使用TypeScript。
编写良好的单元测试应该在合理的范围内覆盖生产代码。通过适当的同行评审过程,结对编程可以检测到的不仅仅是语法错误。错误;请使用像eslint 这样的linter。 TypeScript 可以为这些添加额外的安全层,但我认为这在编程语言要求列表中很低。
TypeScript 并非健全的类型系统
我认为这可能是当前版本的TypeScript 面临的主要问题,但让我们首先定义什么是正常和不健康的类型系统。
健全
声音类型系统确保程序永远不会处于无效状态。例如,如果表达式的静态类型是字符串,则保证在运行时求值期间仅获取字符串。
健全的类型系统确保表达式与其预期类型之间不存在不匹配,无论是在编译时还是在运行时。
当然,健全性也是有层次的,也可以考虑具体的含义。 TypeScript 具有一定程度的理智性,可以检测以下类型的错误:
//无法将类型'string' 分配给类型'number' constincrement=(i: number): number={ return i + '1' } //将类型'98765432'' 的参数分配给类型'number' 我不能这样做它。 Parameters.const countdown:number=Increment('98765432');
不健全
对于Typescript,以下事实非常明确:100% 理智不是其目标,而是TypeScript 非目标列表中的非目标编号3:明确指出:
应用健全或“正确”的类型系统(不是我们的目标)。相反,要平衡准确性和生产力。
这意味着不能保证变量具有运行时定义的类型。我将在下面用一些人为的例子来说明这一点。
Interface A { x: number;} let a: A={x: 3}let b: {x: number | string}=a;b.x='unsound';let x: number=a.x; //异常a.x.toFixed(0);就是这样蚊子?上面的代码是不正确的,因为我们从A接口知道a.x是一个数字。不幸的是,重新分配后,结果是一个字符串,其背后的代码可以编译,但在运行时失败。不幸的是,此处显示的表达式可以正确编译。
a.x.toFixed(0);我认为这可能是TypeScript 最大的问题。这不是为了变得正常。仍有许多运行时错误未被tsc 编译器标记,如果TypeScript 的系统运行状况良好,则可能会发生这种情况。采用这种方法意味着TypeScript 陷入健康和不健康阵营之间。当您遇到下面描述的任何类型时,这种挥杆轨迹会变得更加严重。这很令人沮丧,因为我仍然必须编写尽可能多的测试。当我第一次开始使用TypeScript 时,我得出了一个错误的结论:我不需要再编写那么多单元测试了。
TypeScript 挑战现状,认为减少用户类型使用的认知开销比类型理智更重要。
TypesScript 选择这条道路的原因是可以理解的。一些人认为,如果类型系统100% 保证健全,那么TypeScript 的采用率就不会那么高。随着Dart 语言的日益流行(随着Flutter 的广泛使用),这种观点也被证明是错误的。健全性是Dart 语言的一个目标,可以在这里讨论。
遗憾的是,TypeScript 的不健全性以及它为严格类型系统打开的许多天窗使其效率降低,并使其如今处于相当无用的位置。我希望随着TypeScript 的日益普及,将会有更多的编译器选项可用,让高级用户能够争取100% 的理智。
TypeScript 不保证任何运行时类型检查
运行时类型检查不是TypeScript 的目的之一,因此这个愿望可能永远无法实现。例如,在处理从API 调用返回的JSON 负载时,运行时类型检查非常有用。如果我们可以在类型级别控制这一点,我们就可以避免很多错误和大量单元测试。
运行时无法保证任何事情,因此可能会发生以下情况:
const getFullName=async (): string={ const person: AxiosResponse=wait api(); //response.name.fullName 可能在运行时未定义return response.name.fullName} 支持此要求的库有几个(例如io )。 -ts; 这很好,但您可能需要复制模型。
可怕的 any 类型和严格选项
any 类型是文字,编译器允许any 操作或赋值。
TypeScript 往往非常适合处理小事情,但人们倾向于为需要超过一分钟的事情赋予any 类型。我最近正在做一个Angular 项目,我有很多代码,如下所示:
typeScript 可以让您忘记类型系统。您可以使用any 删除所有类型。
('Oh my god' as any).ToFixed(1); //还记得我所说的关于理智吗?严格的编译器选项启用以下编译器设置,使其看起来更理智:Masu。
strictNullChecks noImplicitAny noImplicitThis always严格和eslint 规则@typescript-eslint/no-explicit-any。
当它们激增时,就会破坏类型系统的健康状况。
结论
我是TypeScript 的粉丝,并在日常工作中使用它,但我认为它有很多缺陷,而且炒作有点过头了。 Airbnb 声称TypeScript 可以防止38% 的错误。我非常怀疑这个确切的百分比数字。 TypeScript 并不是对现有良好实践的补充。您仍然需要编写尽可能多的测试。不管你相信与否,因为我编写了更多代码,所以我可能必须编写更多类型测试。我仍然遇到意外的运行时错误。
TypeScript 提供相对基本的类型检查,但健全性和运行时类型检查不是其目的。这使得TypeScript 的一只脚位于好的一侧,另一只脚位于另一侧。在现在的破船上。
TypeScript 的亮点在于其出色的IDE 支持。例如,如果您在vscode 中输入错误的内容,您将获得视觉反馈。
vscode 中的TypeScript 错误
TypeScript 还提供增强的重构功能,允许您在修改后的代码上运行TypeScript 编译器,以立即识别代码中断(例如方法签名的更改)。
TypeScript 提供了良好的类型检查,显然比没有类型检查器或使用简单的eslint 更好,但我认为它可以走得更远。此外,它应该为像我们这样需要更多功能的用户提供足够的编译器选项。
关注我,转发这篇文章,私信我“Stay Informed”,即可免费获得价值4999元的InfoQ迷你书。
版权声明:本文由今日头条转载,如有侵犯您的版权,请联系本站编辑删除。