how to use a typescript interface as an enum?

Viewed 32

I'm working with a library proto file that generates an interface, that should be able to be used as an enum:

export interface FinishReasonMap {
  NULL: 0;
  LENGTH: 1;
  STOP: 2;
  ERROR: 3;
  FILTER: 4;
}

The types are auto-generated from a .proto definition, so its hard to update them to be a basic enum.

now, I can use that in my own type def like:

export type ImageObject = {
  finishReason?: FinishReasonMap[keyof FinishReasonMap];
}

but I'm not able to use it for a comparison, eg:

if (item.finishReason === FinishReasonMap.FILTER) { ...

error: 'FinishReasonMap' only refers to a type, but is being used as a value here.

I know TS enum's are a bit funky sometimes, but not clear how to use this. I think I want something like the opposite of typeof to get enum values from the interface?

1 Answers

TS is pretty much in the right here.

You are using an interface there so the syntax NULL:0 doesn't specify that NULL has value 0, but that the type of NULL is 0. This, in the end, will force anyone implementing the interface to assign 0 to NULL.

You can see this in action here:

export interface FinishReasonMap {
  NULL: 0;
  LENGTH: 1;
  STOP: 2;
  ERROR: 3;
  FILTER: 4;
}

export class FinishReasonMapT implements FinishReasonMap {
    NULL:0 = 0;
    LENGTH:1 = 1;
    STOP:2 = 2;
    ERROR:3 = 3;
    FILTER:4 = 4;
}

The bottom line is that when you're trying to do FinishReasonMap.FILTER you are trying to access a type (interface) and that doesn't work at runtime.

I don't know of any way of converting that interface to a runtime value that you can use.

Your most likely course of action is to change the generated code to either an enum of an const object.

Related