约束处理每一种情况

问题

type Bird = { kind: 'bird'; legs: number; wings: 2 };
type Dog = { kind: 'dog'; legs: number };
type Fish = { kind: 'fish'; fins: number };

type Animals = Bird | Dog | Fish;

/**
 * 获取动物的附肢数量
 */
function animalAppendAges(animal: Animals): number {
  switch (animal.kind) {
    case 'bird':
      return animal.wings + animal.legs;
    case 'dog':
      return animal.legs + 1; // 1 是尾巴
  }
}

const fishAppendAges = animalAppendAges({ kind: 'fish', fins: 2 });
console.log(fishAppendAges);

看上面这个例子,我该怎么写才能保证 switch 语句里覆盖了本应该有的所有情况?

在线试一试

剧透预警线

解答

type Bird = { kind: 'bird'; legs: number; wings: 2 };
type Dog = { kind: 'dog'; legs: number };
type Fish = { kind: 'fish'; fins: number };

type Animals = Bird | Dog | Fish;

/**
 * 获取动物的附肢数量
 */
function animalAppendAges(animal: Animals): number {
  switch (animal.kind) {
    case 'bird':
      return animal.wings + animal.legs;
    case 'dog':
      return animal.legs + 1; // 1 是尾巴
  }
  const neverHappens: never = animal;
  return neverHappens;
}

const fishAppendAges = animalAppendAges({ kind: 'fish', fins: 2 });
console.log(fishAppendAges);

我们可以通过断言never类型的方法,如果一个联合类型在上面的代码都处理过了,那最终剩下的就可以断言成never,反过来说,如果联合类型不能被断言能never,就意味着没有被处理完全。

在线试一试