首页 > 解决方案 > 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 - 现场示例

标签: javascriptflowtype

解决方案


您必须将Animal类型设置为接口,因为它将您的类型实现描述为“父级”。如果您通过联合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);


推荐阅读