流类型扩展对象类型

时间:2018-11-12 10:17:30

标签: javascript flowtype

作为JavaScript开发人员,我不熟悉类型检查,因此我很难理解为什么这个简单的代码不起作用:

type Animal = {
  id: number,
  name: string,
  type: 'dog' | 'cat'
};

type Dog = {
  id: number,
  name: string,
  type: 'dog',
  color: string
};

function printAnimal(animal: Animal): string {
  return `${animal.type}: ${animal.name}`;
}

const buddy: Dog = {
  id: 1,
  name: 'Buddy',
  type: 'dog',
  color: 'black'
}

printAnimal(buddy);

我要在这里实现的是要有一个接受接口的方法。但是,这给了我错误:Cannot call 'printAnimal' with 'buddy' bound to 'animal' because string literal 'dog' [1] is incompatible with string literal 'cat' [2] in property 'type'.

我尝试过的事情:

  1. interface Animal { // ...}-不起作用。
  2. buddy中删除键入-可以,但是我不满意。有时候我确实想拥有更严格的类型(所以我知道我要与狗而不是猫打交道),但仍然使用可以接受任何动物的通用方法。
  3. 我尝试将type: 'dog' | 'cat'更改为type: string-不起作用。我希望'dog'字符串是常规string类型的子类型,但不是。另一方面,即使它可以工作还不够-有时我知道我的应用程序只接受狗和猫,而不接受任何其他动物。

感谢您的阅读,希望我能从你们那里得到一些帮助!这是实时版本:Try Flow - live example

1 个答案:

答案 0 :(得分:1)

您必须使Animal类型成为接口,因为它会将您的类型实现描述为“父项”。如果您通过通过 union 扩展Dog类型来实施它,那将是有道理的,因为这是使用类型进行更强类型检查的点。

可以这样写:

/* @flow */

interface Animal {
  id: number,
  name: string,
  type: 'dog' | 'cat'
};

type Dog = Animal & {
  type: 'dog',
  color: string
};

function printAnimal(animal: Animal): string {
  return `${animal.type}: ${animal.name}`;
}

const buddy: Dog = {
  id: 1,
  name: 'Buddy',
  type: 'dog',
  color: 'black'
}

printAnimal(buddy);