Converting an integer into a String Enum in TypeScript can result in an undefined value being returned

Issue with Mapping Integer to Enum in TypeScript

export enum MyEnum {
    Unknown = 'Unknown',
    SomeValue = 'SomeValue',
    SomeOtherValue = 'SomeOtherValue',
  }

Recently, I encountered a problem with mapping integer values to my string enums in TypeScript. Despite registering the enum correctly, when trying to map an integer value to MyEnum, it unexpectedly returns undefined.

const myIntValue = 1;
const myEnumValue = MyEnum[myIntValue]; // This behavior raises undefined result

var myCondition = myEnumValue === MyEnum.SomeValue; // However, this comparison wrongly evaluates to false

I am seeking assistance on how to efficiently obtain the correct Enum value in typescript during comparisons or at least make sure it works as expected in conditional statements.

Answer №1

You are presented with two choices.

Option one involves making changes to your enum.

enum MyEnum {
    Unknown = 1,
    SomeValue,
    SomeOtherValue,
}

const myIntValue = 1;
const myEnumValue = MyEnum[myIntValue]; // string

If you eliminate the value 1 from the MyEnum definition, it will commence at 0.

In my opinion, I am not in favor of this solution due to the fact that a numerical enum may not be the optimal selection.

An example to ponder:

const foo = (en: MyEnum) => 42

foo(99999) // ok

The second option is as follows.

You can associate integers with the enum using a tuple:

const enum MyEnum {
    Unknown = 'Unknown',
    SomeValue = 'SomeValue',
    SomeOtherValue = 'SomeOtherValue',
}

const MapEnum = [MyEnum.Unknown, MyEnum.SomeValue, MyEnum.SomeOtherValue] as const;

const result = MapEnum[1] // MyEnum.SomeValue

Remember, enum/object keys do not retain order, hence creating such a tuple dynamically may pose risks.

UPDATE

The second option functions although it comes with higher susceptibility to errors ...

enum MyEnum {
    Unknown = 'Unknown',
    SomeValue = 'SomeValue',
    SomeOtherValue = 'SomeOtherValue',
}

type TupleUnion<U extends string, R extends any[] = []> = {
    [S in U]: Exclude<U, S> extends never ? [...R, S] : TupleUnion<Exclude<U, S>, [...R, S]>;
}[U];

const MapEnum: TupleUnion<MyEnum> = [MyEnum.Unknown, MyEnum.SomeValue, MyEnum.SomeOtherValue,];

No chance of omitting any value

An alternative method without permutation:

enum MyEnum {
    Unknown = 'Unknown',
    SomeValue = 'SomeValue',
    SomeOtherValue = 'SomeOtherValue',
}

// credits goes to https://stackoverflow.com/a/50375286
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
    k: infer I
) => void
    ? I
    : never;

// Credits goes to https://github.com/microsoft/TypeScript/issues/13298#issuecomment-468114901
type UnionToOvlds<U> = UnionToIntersection<
    U extends any ? (f: U) => void : never
>;

type PopUnion<U> = UnionToOvlds<U> extends (a: infer A) => void ? A : never;

type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;

type UnionToArray<T, A extends unknown[] = []> = IsUnion<T> extends true
    ? UnionToArray<Exclude<T, PopUnion<T>>, [PopUnion<T>, ...A]>
    : [T, ...A];

type Result = UnionToArray<MyEnum>

const MapEnum: UnionToArray<MyEnum> = [MyEnum.Unknown, MyEnum.SomeValue, MyEnum.SomeOtherValue,];

For more examples, visit my blog

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for managing update logic in the server side with sveltekit

Currently, I am using Sveltekit and I am facing a dilemma regarding updating input data. The actual update process is straightforward, but there is an issue that arises when trying to send an update API request immediately, as it requires an accessToken to ...

When using Angular's .navigateByUrl() method, it successfully navigates to the desired page, however the html content is not

Whenever I try to navigate to the home page after logging in, I encounter an issue. I have a navbar <app-header></app-header> with two links - one for signing up and another for logging in. After successfully logging in, my goal is to navigate ...

When using ngStyle to bind a variable, the binding variable will be null

Currently, I am attempting to utilize ngStyle to set the background image. <div class="artist-banner fluid-banner-wrapper" [ngStyle]="{'background-image': 'url(../imgs/banner/' + event?.category + '.jpg)' }"> The fun ...

Typescript interface requiring both properties or none at all

I possess key-value pairs that must always be presented together in a set. Essentially, if I have one key with its value A:B, then there should also be another key with its value C:D. It is permissible for the object to contain neither pair as well. (An ex ...

The server's response is unpredictable, causing Json.Parse to fail intermittently

I have encountered a strange issue that is really frustrating. It all started when I noticed that my Json.Parse function failed intermittently. Here is the code snippet in question: const Info = JSON.parse(response); this.onInfoUpdate(Info.InfoConfig[0]); ...

Implementing a back button in an RTL layout with Ionic 2

Just starting an Ionic 2 app in Arabic language requires a RTL layout. I decided to go with the side menu template. Adding the following line for configuring the app to RTL perfectly changed everything's direction, except for the back button which st ...

Is it possible for two distinct TypeScript interfaces to share identical keys while allowing for varying values?

Is it possible in TypeScript to ensure that objValidator has the same keys as the obj it validates, with different key values? Any suggestions on how I can achieve this requirement? Specifically, the obj and objValidator should share identical keys. I wan ...

Guide to creating varying component sizes using ReactJS and Styled Components

Is it possible to add variation to my button based on the prop 'size' being set to either 'small' or 'medium'? interface Props { size?: 'medium' | 'small'; } How can I adjust the size of the component us ...

How to create classes in typescript without utilizing the class keyword

As someone new to TypeScript, I have a curious question about classes. In pre-ES6 JavaScript, there were no classes. So, naturally, one would think it's possible to avoid using them in TypeScript as well. However, I am struggling to figure out the c ...

Is it possible to implement typed metaprogramming in TypeScript?

I am in the process of developing a function that takes multiple keys and values as input and should return an object with those keys and their corresponding values. The value types should match the ones provided when calling the function. Currently, the ...

When a file is modified in Angular, it triggers an error prompting the need to restart the 'npm' service

Whenever I make changes to a file in my Angular application, I encounter the following error: ERROR in ./src/app/@theme/components/auth/index.js Module build failed: Error: ENOENT: no such file or directory, open 'C:\Dev\Ng\ngx-a ...

The outcome of spawning Node.js is as follows: Python3 is unable to open the file './test' due to the error message [Errno 2] indicating that the file or directory does not exist

I am currently trying to execute a basic python script named test.py using the child process in Node JS, however I keep receiving an error message stating python3: can't open file './test': [Errno 2] No such file or directory. Despite my eff ...

The condition in a Typescript function that checks for strings will never evaluate to true

I encountered a strange issue with a TypeScript condition in a function. Here is my current code, where the parameters are passed from outside: getLevel(validation: string, status: string): string { let card = ""; if (validation == &qu ...

What steps are necessary to ensure that the extended attribute becomes mandatory?

Utilizing Express, I have set specific fields on the request object to leverage a TypeScript feature. To achieve this, I created a custom interface that extends Express's Request and includes the additional fields. These fields are initialized at the ...

Utilizing Leaflet-geotiff in an Angular 6 Environment

I'm currently facing an issue where I am unable to display any .tif image on my map using the leaflet-geotiff plugin. I downloaded a file from gis-lab.info (you can download it from this link) and attempted to add it to my map, but I keep encountering ...

What happens when a typed Array in Typescript has an undefined property?

I've encountered an issue with a seemingly simple problem that's causing me quite the headache. The code snippet in question is provided below: interface IFoo{ ReturnFirstBarObject1(): string; FillBarArray(array: Array<Bar>): void; } ...

You cannot assign void to a parameter expecting a function with no return value

I have been working on an angular application that was initially developed in Angular 2, then upgraded to versions 7 and 9, and now I'm attempting to migrate it to Angular 11. There is a function in my code that fetches the notification count for the ...

Learn how to securely download files from an Azure Storage Container using Reactjs

I'm currently working on applications using reactjs/typescript. My goal is to download files from azure storage v2, following a specific path. The path includes the container named 'enrichment' and several nested folders. My objective is to ...

Trouble encountered while configuring and executing Electron combined with React, Typescript, and Webpack application

I am currently in the process of migrating my Electron application from ES6 to Typescript. Despite successfully building the dll and main configurations, I encounter a SyntaxError (Unexpected token ...) when attempting to run the application. The project c ...

Having issues with TypeScript while using Redux Toolkit along with Next Redux Wrapper?

I have been struggling to find a solution. I have asked multiple questions on different platforms but haven't received any helpful answers. Can someone please assist me? Your help is greatly needed and appreciated. Please take some time out of your bu ...