TypeScript:生成枚举值的类型或接口

时间:2019-05-07 09:06:02

标签: html reactjs typescript enums

我想要一个由枚举值生成的接口。我在React中有以下用例:

我有一个可能有很多键值对的枚举。每个枚举值都用作表单ID,因此我在事件侦听器中获得了输入元素的名称和值。我想将状态设置为this.setState({ name: value }),但是名称,描述等应该是类型安全的。

因此,我需要以某种方式从枚举的值中生成一个接口(因为接口不能从枚举继承),以便能够执行以下操作:this.setState({ name: 'hello world' })this.setState({ description: 'a description' }) < / p>

enum InputIDs {
    NAME = 'name',
    DESCRIPTION = 'description',
    // ... many more items ...
}

interface IMyReactComponentState {
    alreadyExisting: boolean;
    [InputIDs.NAME]: string;
    // ... all other items from the Test enum should go here but I'd like to generate it somehow ...
}

class MyReactComponent extends React.Component< ISomeProps, IMyReactComponentState > {
    constructor(props: ISomeProps) {
        super(props);
        this.state = {
            alreadyExisting: false,
            [InputIDs.NAME]: '',
            // more default values
        }
    }

    private handleChange = (event: React.FormEvent<HTMLDivElement>) => {
        // TODO make type safe
        const {name, value}: {name: any, value: string} = (event.target as any); // event.target is either HTMLInputElement, HTMLSelectElement or HTMLTextAreaElement

        // store the value of the corresponding input in state to preserve it when changing tabs
        this.setState({
            [name]: value
        });
  }

}

我的问题是,以下几方面是不可能的:

interface IMyReactComponentState extends InputIDs {
    alreadyExisting: boolean;
}

有什么想法可以使IMyReactComponentState类型的枚举保持同步,而无需自己编写接口?

提前谢谢!不知道是否已经有人问过-如果是这样,我还没有找到答案!


编辑(2019年5月8日):

我们在项目中使用TypeScript 2.8.1

3 个答案:

答案 0 :(得分:1)

您需要使用交叉点和映射类型(应该使用预定义的Record映射类型)

enum InputIDs {
    NAME = 'name',
    DESCRIPTION = 'description',
    // ... many more items ...
}

type IMyReactComponentState = {
    alreadyExisting: boolean;
} & Record<InputIDs, string>

class MyReactComponent { // simplified
    state:IMyReactComponentState
    constructor() {        
        this.state = {
            alreadyExisting: false,
            [InputIDs.NAME]: '',
            [InputIDs.DESCRIPTION]: ''
        }
    }
}

答案 1 :(得分:1)

您可以使用mapped types生成以枚举值作为键的类型,然后使用intersection或使用其他属性对其进行扩展:

type InputValues = {
    [key in InputIDs]: string
}

然后

type IMyReactComponentState = InputValues & {
    alreadyExisting: boolean
};

或者:

interface IMyReactComponentState extends InputValues {
    alreadyExisting: boolean
}

答案 2 :(得分:0)

您可以将IMyReactComponentState定义为

interface IMyReactComponentState {
    alreadyExisting: boolean;
    [key in keyof typeof InputIDs]: string 
}