对象

时间:2018-03-30 16:25:09

标签: flowtype

我有一个对象数组。对象必须具有LabelKey键和可选的IdKey。例如:

const items: ListItem = [
  { name:'Apple', fruit:'apple' },
  { name:'Orange', fruit:'orange' }
];

alert({
  items,
  labelKey: 'name', // defaults to "label"
  idKey: 'fruit', // defaults to "id"
});

我正在尝试为ListItem定义一个类型。

可以选择IdKey

我试过了:

type LabelKey = string | 'label'
type IdKey = 'id' | string
type ListItem = {
   [LabelKey]: string,
   [IdKey]?: any
}

然而,它就像对待“索引者”一样对待它们。并且IdKey上的问号显然是语法错误。

1 个答案:

答案 0 :(得分:2)

根据您的描述和示例,我猜您要定义具有两个动态属性的对象类型,其中一个是可选的,因此这两个对象应该是相同的类型:

var v1: YourType = {
    anything: 'anything',
    another: 'another'
};

var v2: YourType = {
    different: 'anything'
}

如果是这样,我认为使用flowtype无法实现。对象属性名称是该类型的一部分。它无论如何都不能是除了字符串以外的任何东西。

无法定义可以像以下方式使用的对象:

function doStuff(items, labelKey, idKey) {
    for (i in items) {
        var key = items[i][labelKey]
        var id  = items[i][idKey]
    }
}

在这种情况下,唯一的方法是使用Array<Object>类型

您可以做的是定义特定属性的类型。从您的示例中,它可能是

type Fruit = {
    name: string,
    fruit: ?string // not "fruit?: string"
}

type FruitsList = Array<Fruit>

const items: FruitsList = [
  { name:'Apple', fruit:'apple' },
  { name:'Orange', fruit:'orange' }
];

如果要处理具有不同/混合属性的对象,可以使用联合类型。

两个例子:

首先:不同的数组类型,更严格

type Fruit = {
  name: string,
  fruit: ?string
};

type FruitsList = Array<Fruit>;

type Vegetable = {
  name: string,
  vegetable: ?string
};

type VegetablesList = Array<Vegetable>;

type ArrayOfFruitsOrArrayOfVegetables = FruitsList | VegetablesList;

let items1: FruitsList = [
  { name:'Apple', fruit:'apple' },
  { name:'Orange', fruit: undefined }
];

// OR

var items2: VegetablesList = [
  { name:'Cucumber', vegetable:'cucumber' },
  { name:'Potato', vegetable: undefined }
];

function testFirst(items: ArrayOfFruitsOrArrayOfVegetables) {
 return items;
}

testFirst(items1);
testFirst(items2);

Check it out in sandbox

二。 具有不同类型的对象数组,不太严格

type Fruit = {
  name: string,
  fruit: ?string
}

type Vegetable = {
  name: string,
  vegetable: ?string
}

type Grocery = Fruit | Vegetable

type ArrayOfGroceries = Array<Grocery>

// so usage is

var items: ArrayOfGroceries = [
    { name:'Apple', fruit:'apple' },
    { name:'Orange', fruit: undefined },
    { name:'Cucumber', vegetable:'cucumber' },
    { name:'Potato', vegetable:undefined }
];

function testSecond(items: ArrayOfGroceries) {
  return items
}

testSecond(items)

sandbox

一些文档:

Maybe Types

Object Types

Array Types