您的位置:首页> 前端教程> TS教程

TypeScript 可辨识联合类型

2019-5-18 18:26| 作者: admin| 查看: 1177| 评论: 0|来自: 蚂蚁部落

可以合并字符串字面量类型,联合类型,类型保护和类型别名来创建一个叫做可辨识联合类型。

TypeScript基于已有的JavaScript模式, 具有3个要素:

(1).具有普通字符串字面量属性—可辨识的特征。

(2).一个类型别名包含类型的联合—联合。

(3).此属性上的类型保护。

代码实例:

[typescript] 纯文本查看 复制代码
interface Square {
  kind: "square";
  size: number;
}
interface Rectangle {
  kind: "rectangle";
  width: number;
  height: number;
}
interface Circle {
  kind: "circle";
  radius: number;
}

声明三个接口,每个接口都有kind属性,但有不同的字符串字面量类型, kind属性称做可辨识的特征或标签,其它的属性则特定于各个接口。

[typescript] 纯文本查看 复制代码
type Shape = Square | Rectangle | Circle;

将三个类型联合起来,组成一个联合类型,并重命名。

[typescript] 纯文本查看 复制代码
function area(shape: Shape) {
  switch (shape.kind) {
    case "square": return shape.size * shape.size;
    case "rectangle": return shape.height * shape.width;
    case "circle": return Math.PI * shape.radius ** 2;
  }
}

通过类型保护,实现辨识联合类型中的每一个类型;关于类型保护参阅TypeScript 类型保护一章节。

完整性检查:

当没有涵盖所有可辨识联合的变化时,想让编译器可以通知我们。

例如,如果添加Triangle到Shape,同时还需要更新area:

[typescript] 纯文本查看 复制代码
type Shape = Square | Rectangle | Circle | Triangle;
function area(s: Shape) {
  switch (s.kind) {
    case "square": return s.size * s.size;
    case "rectangle": return s.height * s.width;
    case "circle": return Math.PI * s.radius ** 2;
  }
  // 应该报错,因为没有处理Triangle
}

有两种方式可以实现。 首先是启用--strictNullChecks并且指定一个返回值类型:

[typescript] 纯文本查看 复制代码
function area(s: Shape): number { // error: returns number | undefined
  switch (s.kind) {
    case "square": return s.size * s.size;
    case "rectangle": return s.height * s.width;
    case "circle": return Math.PI * s.radius ** 2;
  }
}

因为switch没有包涵所有情况,所以TypeScript认为这个函数有时候会返回undefined。

如果明确地指定了返回值类型为number,那么看到一个错误,因为实际上返回值的类型为number | undefined。 然而,这种方法存在些微妙之处且--strictNullChecks对旧代码支持不好。

第二种方法使用never类型,编译器用它来进行完整性检查:

[typescript] 纯文本查看 复制代码
function assertNever(x: never): never {
  throw new Error("Unexpected object: " + x);
}
function area(shape: Shape) {
  switch (shape.kind) {
    case "square": return shape.size * shape.size;
    case "rectangle": return shape.height * shape.width;
    case "circle": return Math.PI * shape.radius ** 2;
    default: return assertNever(shape); // error here if there are missing cases
  }
}

assertNever检查shape是否为never类型—即为除去所有可能情况后剩下的类型。

如果忘记了某个case,那么shape将具有一个真实的类型并且你会得到一个错误。 这种方式需要定义一个额外的函数,但是在你忘记某个case的时候也更加明显。


鲜花

握手

雷人

路过

鸡蛋

最新评论

返回顶部