How can I efficiently extract a list of keys or numbers from an enum using TypeScript?

Is there a simple method to extract only the keys from an enumerator without returning both keys and values? The Object.keys() function returned 6 keys (0-5) when I tried it, likely because iterating through the enum with forEach also retrieved the values. I want a straightforward way to extract just the keys without having to manipulate another list.

I plan to implement this in a React application

My enumerator:

enum ObservationType {
    Accomodation = 1,
    Addtional = 2,
    LandTransport = 3
}

Here is a code snippet that I attempted, which ended up displaying all six values:

{Object.keys(ObservationType).map((type) => <div>{type}</div>)}

Answer №1

Give this a shot:

Object.keys(enumObj).filter(key => isNaN(Number(key)))

This method works well for handling various types of enums, including Heterogeneous enums.

Answer №2

According to the TypeScript enum documentation:

The generated code for an enum consists of an object that maintains both forward (name -> value) and reverse (value -> name) mappings. References to other enum members are always outputted as property accesses and never inlined.

It's important to note that reverse mapping is not created for string enum members.

This implies that using string enums may be advantageous, for example:

enum ObservationType {
  Accomodation = 'Acc',
  Addtional = 'Addt',
  LandTransport = 'LandT',
}

// Object.keys will only contain the three keys.

An alternative approach to address this issue would be to keep track of the mapped values in order to obtain reverse mappings just once. However, this requires assigning the numeric keys to the object first, which is not always guaranteed:

enum ObservationTypeNums {
  Accomodation,
  Addtional,
  LandTransport,
}

Object.keys(ObservationTypeNums).reduce((arr, key) => {
  if (!arr.includes(key)) {
    arr.push(ObservationTypeNums[key]);
  }
  return arr;
}, []);

// The array now contains only the string keys

Alternatively, you can filter out the numeric keys similar to how it has been done previously.

Answer №3

Consider utilization of ts-enum-util (GitHub, npm):

import {$enum} from "ts-enum-util";

enum ObservationType {
    Accomodation = 1,
    Addtional = 2,
    LandTransport = 3
}

// type: ObservationType[]
// value: [1, 2, 3]
const values = $enum(ObservationType).getValues();

// type: ("Accomodation" | "Addtional" | "LandTransport")[]
// value: ["Accomodation", "Addtional", "LandTransport"]
const keys = $enum(ObservationType).getKeys();

// direct mapping of enum value/key pairs
const valueDivs = $enum(ObservationType).map(
    (value, key) => <div>{value}</div>
)

This library helps handle the numeric key reverse lookup entries in the runtime enum object, among other functionalities.

Answer №4

What do you think of this solution?

Object.keys(ObservationType).filter(key => Number.isNaN(Number(key)))

Huge thank you to @basarat for inspiring this answer.

Answer №5

I struggled to find a satisfactory solution to this problem.

It appears that the enum generates an Object in this manner:

{
  key0: 0,
  key1: 1,
  0: key0,
  1: key1
}

Here is my approach:

const observationTypes: string[] = Object.keys(ObservationType).filter((_, i) => ObservationType[i] !== undefined).map((_, i) => ObservationType[i]);

This results in an array of strings:

{
  0: "a",
  1: "b",
  2: "c",
  3: "d",
  4: "e",
  ...
}

You can easily adjust this code snippet to create a set of elements as described in your query.

Answer №6

If you are dealing with string enums (enums with string values), you can easily retrieve the keys and values using Object.keys(myEnum) and Object.values(myEnum).

For numeric enums, it is recommended to use these methods instead of relying on isNaN, as it may lead to unexpected results for certain keys:

/**
 * Retrieve the values for a numeric enum.
 */
export function enumValues(myEnum) {
    return Object.values(myEnum).filter((o) => typeof o == 'number');
}

/**
 * Retrieve the keys for a numeric enum.
 */
export function enumKeys(myEnum) {
    return Object.values(myEnum).filter((o) => typeof o == 'string');
}

Answer №7

The ObservationType object contains keys such as Accomodation, Additional, LandTransport, 1, 2, 3, and plays a crucial role in understanding the functionality of enums in TypeScript.

If you are interested in retrieving only the string names, you can easily achieve this using a basic filter:

{Object.keys(ObservationType)
  .filter(k => typeof key === 'string')
  .map((type) => <div>{type}</div>)}

Answer №8

To easily retrieve the values associated with the keys of an enum, you can utilize the following technique where ObservationType[key] will give you the value for each key as needed.

(Object.keys(ObservationType) as Array<keyof typeof ObservationType>).map((key, index) => {}) 

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

Determining the function return type by analyzing an array of functions

If you have a vanilla JavaScript function that accepts an array of callbacks (each returning an object) and combines their outputs, how can TypeScript be used to determine the return type of this function? While ReturnType is typically used for a single ...

Using React-Bootstrap with TypeScript in your project

I'm currently working on creating a navigation bar using react-bootstrap. I've already installed the node-module as follows: "@types/react-bootstrap": "^0.32.11",. However, when I try to use it in my hello.tsx component, I encounter a compile err ...

Issue encountered when attempting to deploy a node/express API with now.sh

Currently, I am in the process of deploying a node/express API with multiple endpoints on now.sh. I am seeking guidance on properly configuring the now.json file for this deployment. In order to provide a visual representation of my project's comple ...

Analyzing arrays and object key/value pairs based on a specific value in javascript

I want to create a new object with key/value pairs. The new object should include values from an existing key/value object as well as unique values from an array. Here is the array: [{ name: "Computer", name: "Car", name: "House&q ...

Refining Interface Properties by Eliminating Null Options

I am facing an issue with an interface property that can be null. I need to ensure it's not null before passing the object into a typesafe object. While narrowing works when assigning the property to a variable, it seems to fail when trying to use th ...

initiating nest start removes the json files in the dist directory

As I work on my nestjs application, I find myself needing to ensure that specific json files are copied to the dist directory. This is especially important for the "engines" folder, where the json files in src/engines must be replicated in dist/and prod. ...

Creating personalized directives

Seeking help on Vue's custom directives with Typescript integration. Despite extensive search online and in chat rooms, I am unable to find any solutions. <button v-clickOutside="myFunc"> Click Outside </button> Implementing the ...

Navigating in Angular is made easy with the Angular routing feature, which allows you to redirect

I have been working through the Angular Tour of Heroes Guide and encountered the section on the "default route". I decided to experiment by removing the pathMatch attribute from the Route associated with an empty string. Below is the code snippet in quest ...

Learn the process of importing different types from a `.ts` file into a `.d.ts` file

In my electron project, the structure looks like this: // preload.ts import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron' import { IpcChannels } from '@shared/channelNames' contextBridge.exposeInMainWorld('api&a ...

Managing non-mandatory information in a structured domain representation: What's the best approach?

When working on applications or domain models, I often ponder the most effective approach to handling incomplete or optional data. Typed languages like TypeScript and C# offer the advantage of defining models with strict types. While this can be beneficial ...

Ways to resolve: The JSX component does not contain any construction or call signatures

I've been grappling with a persistent issue regarding the creation of custom elements dynamically in React TypeScript. If you're curious, you can check out the question here. const generalButtons: MenuButton[] = [ { text: "New Cl ...

Error message: Deno package code encounters error due to the absence of 'window' definition

I am facing an issue with a npm package I imported into my Deno project. The code in the package contains a condition: if (typeof window === 'undefined') { throw new Error('Error initializing the sdk: window is undefined'); } Wheneve ...

Unable to locate CSS/SCSS Code module in VSCode when using a relative path

I am currently developing a SharePoint Framework web-part in VS Code. Despite my efforts, I am unable to locate my scss styles file, even though it is stored in the same directory - please refer to the image provided below: https://i.sstatic.net/LanF7.pn ...

The TypeScript interface is incorrectly extending another interface, causing a compatibility issue with the 'then' property types

Before casting a downvote without reason, kindly take a moment to check my profile or ask for clarification. Your input, suggestions, and edits are valuable in improving the question further. I've scoured Stack Overflow and searched extensively online ...

Learn how to efficiently transfer row data or an array object to a component within Angular by utilizing the MatDialog feature

My goal is to create a functionality where clicking on a button within a specific row opens up a matDialog box displaying all the contents of that row. Below is the HTML snippet: <tr *ngFor="let u of users"> <td data-label="ID& ...

What is the reason for TypeScript's prioritization of arguments over assignment in generic inference?

When it comes to Typescript generics inference, the priority is given to arguments over assignment. This means that any param props are automatically converted into type unknown, even if they are assigned to a variable whose type param is set to an object ...

The observed function remains untouched

In my code, I have an if condition inside a function that looks like this: public setOption() { setTimeout(() => { if (this.isCMode && !this.quest['isCompleted']) { this.toggleOption(false); } },window['TIME ...

Looking for a type that combines multiple options

I am interested in incorporating union types as function arguments, with the ability to utilize the arguments and have any missing ones default to undefined. However, when it comes to 'name' and 'age', there seems to be a type conflict ...

Exporting items with a label in TypeScript/JavaScript

Is it possible to rename the functions that are exported using the following syntax in Typescript/Javascript? export const { selectIds, selectEntities, selectAll, selectTotal } = adapter.getSelectors(selectState); I would like to import selectAll as sele ...

The comparison between StrictNullChecks and Union Types in terms of syntax usage

Understanding StrictNullChecks in TypeScript Traditionally, null and undefined have been valid first class type citizens in JavaScript. TypeScript formerly did not enforce this, meaning you couldn't specify a variable to potentially be null or unde ...