文章插图
当你学习TypeScript时,你的第一印象可能会欺骗你:这不就是JAVAScript注解的一种方式吗?不就是编译器用来帮助我找到潜在bug的吗?
虽然这种说法没错,但随着你对TypeScript不断了解,你会发现这门编程语言最不可思议的力量在于编写、推断和操作数据类型 。
本文总结的一些技巧,可以帮助大家充分发挥TypeScript的潜力 。
#1 用集合的概念思考问题数据类型是程序员日常要处理的概念,但要简洁地定义它却出奇地困难 。然而我发现集合非常适合用作概念模型 。
刚开始学习TypeScript时,我们常常会发现用TypeScript编写类型的方式很不自然 。举一个非常简单的例子:
type Measure = { radius: number };type Style = { color: string };// typed { radius: number; color: string }type Circle = Measure & Style;
如果你在逻辑AND的意义上解释运算符&,可能会认为Circle是一个虚拟类型,因为它是两种类型的结合,没有任何重叠的字段 。这不是TypeScript的工作方式 。此时通过集合的概念思考更容易推断出正确的行为:- 每个类型都是一系列值的集合 。
- 有些集合是无限的:例如string、object;有些是有限的:例如bool,undefined,...
- unknown?是通用集(包括所有值),而never是空集(包括无值) 。
- 类型Measure是包含radius数字字段的所有对象的集合 。style也是如此 。
- &?运算符创建一个交集:Measure & Style表示包含radius和color的对象集,这实际上是一个较小的集合,字段更常用 。
- 同理,|运算符创建一个并集:一个较大的集合,但常用字段可能较少(如果组合两个对象类型的话) 。
type ShapeKind = 'rect' | 'circle';let foo: string = getSomeString();let shape: ShapeKind = 'rect';// disallowed because string is not subset of ShapeKindshape = foo;// allowed because ShapeKind is subset of stringfoo = shape;
#2 了解声明类型和收窄类型TypeScript中一个非常强大的功能是基于控制流的自动类型收窄 。这意味着变量在代码位置的任何特定点都有两种与之关联的类型:声明类型和收窄类型 。function foo(x: string | number) {if (typeof x === 'string') {// x's type is narrowed to string, so .length is validconsole.log(x.length);// assignment respects declaration type, not narrowed typex = 1;console.log(x.length); // disallowed because x is now number} else {...}}
#3 使用可区分的联合类型而不是可选字段当定义一组多态类型(如Shape)时,很容易这样开始写代码:type Shape = {kind: 'circle' | 'rect';radius?: number;width?: number;height?: number;}function getArea(shape: Shape) {return shape.kind === 'circle' ?Math.PI * shape.radius! ** 2: shape.width! * shape.height!;}
需要非空断言(访问radius、width和height?时),因为kind和其他字段之间没有建立关系 。相反,可区分的联合类型是一个更好的解决方案:type Circle = { kind: 'circle'; radius: number };type Rect = { kind: 'rect'; width: number; height: number };type Shape = Circle | Rect;function getArea(shape: Shape) {return shape.kind === 'circle' ?Math.PI * shape.radius ** 2: shape.width * shape.height;}
从以上代码可以看出,类型收窄消除了强制类型转换的需要 。#4 使用类型谓词避免类型断言如果你以正确的方式使用TypeScript的话,你会发现自己很少使用显式类型断言(比如value as SomeType);但是,有时你可能会冲动地写出诸如这样的代码:
type Circle = { kind: 'circle'; radius: number };type Rect = { kind: 'rect'; width: number; height: number };type Shape = Circle | Rect;function isCircle(shape: Shape) {return shape.kind === 'circle';}function isRect(shape: Shape) {return shape.kind === 'rect';}const myShapes: Shape[] = getShapes();// error because typescript doesn't know the filtering// narrows typingconst circles: Circle[] = myShapes.filter(isCircle);// you may be inclined to add an assertion:// const circles = myShapes.filter(isCircle) as Circle[];
更优雅的解决方案是将isCircle和isRect?更改为返回类型谓词,这样就可以帮助TypeScript在filter调用后进一步收窄类型:function isCircle(shape: Shape): shape is Circle {return shape.kind === 'circle';}function isRect(shape: Shape): shape is Rect {return shape.kind === 'rect';}...// now you get Circle[] type inferred correctlyconst circles = myShapes.filter(isCircle);
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 徐怀钰|《浪姐4》一公录完,谢娜组全员晋级,徐怀钰跳舞放炮,5人被淘汰
- GPT冲击了哪些科技从业者的饭碗?程序员较“惨” 创意类、知识类从业者受益
- 程序员|未来十年,除了程序员,谁都不好混
- “流动型程序员”指的是什么类型的程序员?
- GPT-4解放程序员!GitHub推出Copilot X,动动嘴就能写代码
- 程序员|作为一个程序员为什么今年的工作感觉更难找了呢
- 程序员是什么专业(程序员要考什么证)
- 程序员|职业生涯:纵横螺旋多元通道进化,由内而外综合能力升级
- 程序员用什么键盘(程序员键盘推荐)
- 国足晋级12强赛怎么进世界杯 12强赛怎么晋级世界杯