Jonathan
Jonathan

Reputation: 7551

How can I know at compile-time whether a type is an enum?

I want to write a function that validates that a value is part of an enum, and throw if not. From this answer, I wrote:

    private ensureValueInEnum(enumType: any, value: string): void {
        if (!Object.values(enumType).includes(value)) {
            throw new Exception(`${value} is invalid value. Valid values are: ${Object.values(enumType).join(' / ')}`);
        }
    }

But, I don't like that enumType is any. Is there something I can write that says "enumType is an enum"?

Upvotes: 0

Views: 394

Answers (1)

Alex Wayne
Alex Wayne

Reputation: 187024

Not really, no.

Once compiled, there's nothing magic about enums. They are just objects with string keys and constant values. That type would be Record<string, unknown>.

So I think this type is as tight as your going to get:

function ensureValueInEnum(enumType: Record<string, unknown>, value: unknown): void {
  //
}

If you only want to support enums with string values, then you could do:

function ensureValueInEnum(enumType: Record<string, string>, value: string): void {
  //
}

But there no way to distinguish an enum from, say, this:

const testObj = {
    C: 'c',
    D: 'd',
}

ensureValueInEnum(testObj, 'c') // works
ensureValueInEnum(testObj, 'q') // error

If you want testObj to be a type error, and only enums declared with the enum keyword to be allowed, then I don't think that's possible.

Playground

Upvotes: 1

Related Questions