我希望早点学到关于 Typescript 的七个教训
到目前为止,您可能已经看过关于 TypeScript 崛起的博客文章。在 Stack Overflow 的年度开发者投票中,它在开发者最喜爱的语言中排名第二,在短短两年内飙升至Github上使用率第七的语言,并且在 Google Trends 中稳步增长,而 JavaScript 则基本停滞不前。正因如此,我所在的Netflix Studios(我们正在招聘!)去年宣布,我们所有的官方 UI 库今后都将使用 TypeScript,这或许并不令人意外。
唯一的问题是,我正在编写其中一个库。而且我以前从未使用过 TypeScript,更不用说任何类型语言了(或者……实际上,除了 HTML/CSS/JavaScript 之外的任何其他语言)。所以在过去的一年里,我一直在努力理解“泛型”和“类型推断”之类的概念,并想列出一份清单,列出我希望在开始之前了解的内容。
1. TypeScript 是一门需要单独学习的技能,学习任何新事物都会经历各种心痛和头痛。对于我们大多数人来说,这需要时间和坚持——但这没关系!
在所有关于 TypeScript 将如何拯救 JavaScript 的狂热推文中,人们忽略了一个事实:对于新手来说,TypeScript 的学习难度实在太大。我有一种直觉,很多宣称 TypeScript 让 JavaScript 变得有意义的人,其实都是其他类型语言的。
另一方面,我根本不懂类型语言的词汇,更不用说 TypeScript 了。我坐在那里,用 Google 搜索我遇到的问题(然后在关键词列表中加上“typescript”),却不知道该如何描述,也不知道该用什么词,这真是令人沮丧。当我知道可以用 JavaScript 解决问题,却无法用类型来解决时,这种沮丧感尤其强烈。我花了六个月的时间才适应了这种状态,意识到这个问题有多难,并不再为此自责。
2. 类型库和单纯使用类型是两回事,TypeScript + React 又是另一套需要学习的技能。查找你所在层的具体示例和文档,而不仅仅是通用的 TypeScript 内容。
我一直遇到的一个问题是,很多教程和文档都假设你正在编写应用程序。然而,我发现编写一段库代码需要更复杂的类型——很多东西需要泛型,或者比你在应用程序代码中所能持有的强势观点更加灵活。你被迫学习泛型、条件类型以及一系列你在大多数应用程序中可能不需要的其他 TypeScript 功能。寻找与你正在做的工作相匹配的示例。
3.尽快放弃官方文档。
值得庆幸的是,官方文档在我发布本文之前就更新了,现在浏览起来更加方便,但与其他一些能帮助你更快入门的资源相比,仍然显得逊色。如果你对类型一窍不通,我强烈建议你看看这两个资源。Basarat 的 TypeScript 指南非常全面地介绍了什么是类型,而 Shawn Wang 的 React TypeScript 速查表将帮助你快速学习如何在 React 中使用 TypeScript。
- 通用 TypeScript:https://basarat.gitbook.io/typescript/
- 使用 React 的 TypeScript:https://github.com/typescript-cheatsheets/react-typescript-cheatsheet
4.学习和利用实用程序类型,不要害怕探索类型帮助库。
刚开始的时候,我并没有花太多时间思考如何使用像 这样的辅助方法Pick, Omit, Required
。与 Sass 相比,发现和使用这些方法就像第一次发现嵌套的媒体查询一样。现在,你不再需要面对一堆无聊的重复代码,而是只需依赖已经定义好的东西;将来当你需要重构代码时,只需修改一次,你就会爱上这种做法。
然而,有时你需要更强大的功能——幸运的是,社区已经构建了一些软件包来帮助你轻松上手。探索这些软件包,可以帮助你掌握 TypeScript 的语法后,更好地了解它所能做到的一切。
5. 如果输入太复杂,您的 API 可能会出现设计错误。
有时候,你会觉得有些代码根本无法输入。比如,不同数据集之间的关系太多,语法太复杂,泛型无法正常工作,或者其他类似的问题。
当这种情况发生时(而且肯定会发生),我会告诉年轻的自己退一步,重新审视我正在编写的函数的设计。如果我很难准确地描述一个函数的类型,那么对于其他尝试使用相同函数的人来说,直观地理解它的含义可能也同样困难。
这个建议可能有点不靠谱——有时候问题在于你对 TypeScript 还不够了解(通常,这些复杂的类型需要你具备条件类型或类似知识的高级知识),我最初几个月的情况确实如此。然而,随着你不断探索 TypeScript,你会更清楚地意识到,问题究竟出在知识方面,还是出在 API 设计方面。
6. 类型保护只是对表达式返回 true/false 的函数
这对其他人来说可能显而易见,但对我来说,“类型保护”这个词似乎有点神秘。既然我已经告诉 TypeScript 我要做什么,为什么还要特意运行一个额外的函数来检查类型呢?答案有两个方面。
首先,虽然你的输入可能完全正确,但 TypeScript 只能检查你编写的内容。除非你为外部数据(例如 API)生成类型,否则这些请求可能以任何形式出现,并在运行时破坏你的应用程序。如果你在其中使用了类型保护,你至少可以捕获错误并尝试在 UI 中优雅地处理它。
其次,类型保护允许你在函数内部缩小类型范围。有时你会给函数传递一个可能包含多种不同类型的项(通常通过可区分联合传递),而你的函数并不知道该项属于哪种类型。使用类型保护,你可以告诉 TypeScript 它是一个什么样的项。
7. 泛型很棒,能让你的组件更灵活。但也要忽略使用单字母泛型的糟糕惯例。
最后,我希望年轻时的自己在刚开始学习泛型时不要那么害怕。部分原因是,我读到的文档和教程function Foo(S, T extends keyof S)
看起来完全是胡言乱语。
然而,过了一段时间,我逐渐明白了泛型不过是变量和函数参数的混合体,被转化成了一个类型系统。和变量一样,它们在被定义为引用其值之后可以被复用。和函数参数一样,用户传递泛型时,期望它们能够用于后续的其他计算。和函数参数一样,你可以设置一个默认泛型来帮助用户,而且由于默认泛型是类型而非实际值,因此你也可以指定特定的形状。
哦 - 还有年轻的我? - 请记住,设置默认泛型不会设置类型形状,您仍然需要扩展类型才能做到这一点。
哇,太多了!
感谢大家的阅读!如果您想听听我和Una Kravets在撰写这篇博文时讨论的内容,欢迎在toolsday上收听。如果您有任何问题或想法,欢迎在 Twitter 上关注我@chrisdhanaraj,或在下方留言。
词汇表
如果你和我一样,那么我在这篇文章中使用的一些词语可能不太合理。我整理了一份我引用的 TypeScript 专用词汇列表,并附上了一些链接,以便更好地理解它们。
-
条件类型 - TypeScript 中的条件类型
-
泛型 - TypeScript 泛型讲解
-
实用程序类型 -开箱即用的实用程序类型列表
-
Typeguards -使类型真实化 - typeguard 函数