定义类型脚本接口,其中属性是现有对象的属性

时间:2018-05-23 05:02:27

标签: javascript typescript

定义接口的最佳方法是,其中一个属性可以是现有对象的任何属性。在这种情况下,我有一个名为fruits的对象,我只是存储了许多字符串常量,我想定义一个接口(杂货),使得其中一个属性(fruit)可以是fruits对象中的任何字符串常量。

type Fruits = 'APPLE' | 'BANANA' | 'ORANGE';

const fruits = {
    APPLE: 'APPLE',
    BANANA: 'BANANA',
    ORANGE: 'ORANGE'
}

interface IGroceries {
    fruit: Fruits,
    vegetables: string[]
}

const initialGroceriesState: IGroceries = {
    fruit: fruits.APPLE,
    vegetables: []
}

这是我最好的尝试,但这会引发错误说:

Type '{ fruit: string; vegetables: never[]; }' is not assignable to type 'IGroceries'.
  Types of property 'fruit' are incompatible.
    Type 'string' is not assignable to type 'Fruits'.

2 个答案:

答案 0 :(得分:3)

其中一个选项是切换到string enum

enum Fruits {
    APPLE = 'APPLE',
    BANANA = 'BANANA',
    ORANGE = 'ORANGE'
}

interface IGroceries {
    fruit: Fruits,
    vegetables: string[]
}

const initialGroceriesState: IGroceries = {
    fruit: Fruits.APPLE,
    vegetables: []
}

另一个选项是更正现有对象的输入:

type Fruits = 'APPLE' | 'BANANA' | 'ORANGE';

const fruits: { [key: string]: Fruits } = {
    APPLE: 'APPLE',
    BANANA: 'BANANA',
    ORANGE: 'ORANGE'
}

interface IGroceries {
    fruit: Fruits,
    vegetables: string[]
}

const initialGroceriesState: IGroceries = {
    fruit: fruits.APPLE,
    vegetables: []
}

答案 1 :(得分:0)

fruits键值被推断为字符串。这会导致错误,因为Fruits可分配给字符串类型,但反之亦然。

为避免这种情况,应明确指定fruits类型:

const fruits: { [K in Fruits]: K } = {
    APPLE: 'APPLE',
    BANANA: 'BANANA',
    ORANGE: 'ORANGE'
};

另一种方法是使用字符串枚举,如另一个答案所示。根据具体情况,这可能是也可能不是。