我有一个对象数组。对象必须具有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上的问号显然是语法错误。
答案 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);
二。 具有不同类型的对象数组,不太严格
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)
一些文档: