不兼容的对象类型

Incompatible object types

/* @flow */

type optionsType = Array<{id: string | number, name: string}>;
type modelsType = Array<{id: number, name: string}>;

function getOptions(options: optionsType): string {
  return options.reduce((a, e) => {
    return a + `<option value="${e.id.toString()}">${e.name}</option>`;
  }, '');
}

const options: modelsType = [
  {id: 1, name: 'punto'},
  {id: 2, name: 'duo'},
  {id: 500, name: 'cinquecento'},
];
console.log(getOptions(options));

上面的例子抱怨 Cannot call "getOptions" with "options" bound to "options" because number [1] is incompatible with string [2] in property "id" of array element. 但在我的理解中 modelsType 只是比 optionsType 更通用。为什么流量会报错,我怎样才能让它按预期工作?

如果

let second: secondType = first;

按原样被允许,这意味着这样做是有效的

second.id = "some-id";

但这会破坏 firstType 的类型,因为它是同一个对象,类型是 number,但它现在被分配了一个字符串。

要完成这项工作,您需要指定 secondType.id 是只读的,或者 "covariant"。你可以通过改变

来做到这一点
type secondType = {id: string | number, name: string};

type secondType = {+id: string | number, name: string};

(Example on flow.org/try)

我的用例的最终解决方案:

/* @flow */

type optionsType = $ReadOnlyArray<{+id: string | number, name: string}>;
type modelsType = Array<{id: number, name: string}>;

function getOptions(options: optionsType): string {
  return options.reduce((a, e) => {
    return a + `<option value="${e.id.toString()}">${e.name}</option>`;
  }, '');
}

const options: modelsType = [
  {id: 1, name: 'punto'},
  {id: 2, name: 'duo'},
  {id: 500, name: 'cinquecento'},
];
console.log(getOptions(options));