Home > Software engineering >  How to get the min/max value of Enum in TypeScript
How to get the min/max value of Enum in TypeScript

Time:05-19

I have a const enum in TypeScript, something like below:

const enum ControlId {
   ZoomIn = 600,
   ZoomOut,
   Close, 
   Open,
   ....
}

Given a number, I want to know if it is within the range of ControlId, which is [600, ?], so that I can know if it falls into the category of ControlId or not. I am wondering if there is a way to do that. Thanks.

CodePudding user response:

I think you're saying you have a runtime value and you want to know if it's a valid member of ControlId (you've said you want a "range check," but numeric enums aren't necessarily contiguous).

A const enum has no runtime existence, so you can't write runtime code to validate a number to see if it's a valid member of a const enum.

You can do it if the enum isn't const:

enum ControlId {
    ZoomIn = 600,
    ZoomOut,
    Close, 
    Open,
    // ....
}

function assertIsControlId(value: number): asserts value is ControlId {
    if (!(value in ControlId)) {
        throw new Error(`Invalid ControlId value ${value}`);
    }
}

There I've done it as a type assertion function, but that could be a type guard function instead, or just an inline expression. Basically, if the value is a number, and the value (when converted to string, implicitly by the in operator) is a valid property name for ControlId, it's a valid member of ControlId.

If you really mean you want the min/max, even though the enum values are not guaranteed to be contiguous, you can do that like this:

function getMinMaxOfEnum(e: object) {
    const values = Object.keys(e).map(k => k === "" ? NaN :  k).filter(k => !isNaN(k)).sort((k1, k2) => k1 - k2);
    return [values[0], values[values.length - 1]];
}

(There's probably some better type for e than object. And in modern environments, values[values.length - 1] could be values.at(-1).)

That gets all of the keys from the object you pass in, converts them to number if possible, removes the ones that didn't convert successfully (so now we have an array of enum values), sorts the resulting array, and returns the first and last elements of the array.

Alternatively, use Math.min and Math.max instead of sorting:

function getMinMaxOfEnum(e: object) {
    const values = Object.keys(e).map(k => k === "" ? NaN :  k).filter(k => !isNaN(k));
    return [Math.min(...values), Math.max(...values)];
}

Playground link

  • Related