enum as generic type in typescript

Viewed 88

I would like to declare an interface with a member of type enum, as in - any enum. The idea here is to be a little safer than saying any, but still open to future enum types.

Use case: I'm defining an action interface for redux, and I want the BaseAction interface to be something like this:

export interface BaseAction {
  type: enum;  //this gives an error
  payload: any;
}

Is there a way to declare that the type of a member is any so long as it's an enum?

This way, in the future, I may define this:

export enum SpecificActionType {
  SPECIFIC_1 = "SPECIFIC_ACTION_1",
  SPECIFIC_2 = "SPECIFIC_ACTION_2",
}

export interface SpecificAction1 extends BaseAction {
  type: SpecificActionType.SPECIFIC_1;
  payload: {
    id;
  };
}

As a disclaimer, I'm all new to redux and typescript, but looking for a good rigorous and future proof paradigm that's developer friendly. If you have a better idea, I'm open to that as well.

2 Answers

Basically not a generic type, but a base type. Unfortunately typescript does not enable you to do such a thing. To provide this type of extensibility you need to either:

Redefine the interface each time

export interface BaseAction {
  type: SpecificActionEnum | OtherActionEnum;  
  payload: any;
}

Use the any or the unknown type.

You can add a generic type but can't really enforce that it has to be an enum (AFAIK). But the repr of an enum at least has to be a string or a number.

So this is really more type annotation than any sort of compile-time type checking, but it may make the code more clear:

export interface BaseAction<T extends string | number> {
  type: T;
  payload: any;
}

export enum SpecificActionType {
  SPECIFIC_1 = "SPECIFIC_ACTION_1",
  SPECIFIC_2 = "SPECIFIC_ACTION_2",
}

export interface SpecificAction1 extends BaseAction<SpecificActionType> {
  type: SpecificActionType.SPECIFIC_1;
  payload: {
    id: number;
  };
}

Playground Link

Related