What is the best way to extract all Enum Flags based on a Number in TypeScript?

Given:
Enum: {1, 4, 16}
Flags: 20

When: I provide the Flags value to a function

Then: The output will be an array of flags corresponding to the given Enum: [4, 16]

Note: I attempted to manually convert the Enum to an array and treat values as numbers. However, I encountered difficulties when transitioning to TS and I aim to create a function that is adaptable in case the Enum is modified. I prefer not to hardcode it. Any assistance would be greatly appreciated!

enum Enum {
    one = 1,
    four = 4,
    sixteen = 16,
}

const Flags: number = 20;

function getEnumValues(flags: number): Enum[] {
    const enumFlags = [1, 4, 16];
    
    const enums: Enum[] = [];

    enumFlags.forEach(ef => {
        if ((ef & flags) != 0) {
            enums.push(ef);
        }
    })

    return enums;
}

console.log(getEnumValues(Flags));

Solution referred from: Typescript flagged enum get values. However, this solution does not align with my Enum as it lacks sequences 2 and 8.

Answer №1

If you're worried about constantly listing the Enum values in the enumFlags array within the function, there's a way to generate them dynamically:

const enumFlags = Object.values(Enum)
    .filter((value): value is number => typeof value === "number");

It's important to use the type guard function in the filter callback (such as using a type predicate, like value is number), otherwise TypeScript might incorrectly infer the array type as (string | Enum)[]. By specifying typeof === "number", we ensure that this isn't the case.

Playground link

Sometimes it's beneficial to generate the array just once, right after defining Enum, and then reuse it rather than recreating it each time. While it does come with some cost, it's negligible (and keeping the array also incurs [minimal] memory usage).

Answer №2

I faced a similar challenge previously and coincidentally, I happened to write an article about it because it was quite an intriguing problem.

If you're interested, you can check out the article here: https://dev.to/sincovschi/bitwise-enum-flags-to-generate-html-from-array-3576

To tackle this challenge, you'll first need a helper function that extracts Enum's flags as an array by treating TS enum as a regular object. Once you have this helper in place, you can proceed with your approach by looping through the flags and checking if they exist in your number.

The code snippet below is taken from the code sandbox linked above:

const isPowerOfTwo = (x: number): boolean => {
  return x != 0 && (x & (x - 1)) == 0;
};

export function getEnumFlags<
  O extends object,
  K extends O[keyof O] = O[keyof O]
>(obj: O): K[] {
  const isFlag = (arg: string | number | K): arg is K => {
    const nArg = Number(arg);
    const isNumber = !Number.isNaN(nArg);
    return isNumber && isPowerOfTwo(nArg);
  };

  const enumFlags: K[] = [];

  Object.keys(obj).forEach(key => {
    const nKey = Number(key);
    if (isFlag(nKey)) {
      enumFlags.push(nKey);
    }
  });

  return enumFlags;
}

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

Dealing with implicit `any` when looping through keys of nested objects

Here is a simplified example of the issue I am facing: const testCase = {a:{b:"result"}} for (const i in testCase) { console.log("i", i) for (const j in testCase[i]){ console.log("j", j) } } Encountering ...

Obtaining images from the backend within a component's TypeScript file in a MEAN stack application is a

In my component.ts file, I am looking to retrieve images from the backend/images folder as Image objects. The paths of these images are stored in the database. this.productsService.getProduct(this.editId).subscribe(productData => { this.name = prod ...

angular 2 checkbox for selecting multiple items at once

Issue I have been searching for solutions to my problem with no luck. I have a table containing multiple rows, each row having a checkbox. I am trying to implement a "select all" and "deselect all" functionality for these checkboxes. Below is an example o ...

Identifying a shift in data model within a component

It seems like there's a piece I might be overlooking, but here's my current situation - I have data that is being linked to the ngModel input of a component, like so: Typescript: SomeData = { SomeValue: 'bar' } Snippet from the vie ...

What steps can I take to avoid encountering the `@typescript-eslint/unbound-method` error while utilizing the `useFormikContent()` function?

Recently, I updated some of the @typescript-eslint modules to their latest versions: "@typescript-eslint/eslint-plugin": "3.4.0", "@typescript-eslint/parser": "3.4.0", After the update, I started encountering the fo ...

Error: The property 'children' is not found in type '{ children?: ReactNode; }'

I have been working on implementing the search bar feature from the provided link. Despite my efforts to match the types correctly, I keep encountering a TypeScript error. Homepage.tsx const [searchQuery, setSearchQuery] = useState(query || '' ...

``Are you experiencing trouble with form fields not being marked as dirty when submitting? This issue can be solved with React-H

Hey there, team! Our usual practice is to validate the input when a user touches it and display an error message. However, when the user clicks submit, all fields should be marked as dirty and any error messages should be visible. Unfortunately, this isn&a ...

Create multiple instances of a component in a dropdown menu using different datasets in Angular 5

Outlined below is the structure of my drop-down list: Companies > Depots Each company has multiple depots. I have developed a component for companies, and upon clicking on a company (menu item), an HTTP request is made to bring all companies which are ...

Ways to access nested keys in a TypeScript object as well as an array containing objects

As I develop a form generator, my goal is to achieve type safety for a nested object and an array of objects. Specifically, I want the 'name' property to correspond to the key of the respective object it belongs to. For instance, in the scenario ...

The issue with dispatching actions in TypeScript when using Redux-thunk

As a beginner in TypeScript, I apologize if my question seems silly, but I'll ask anyway: I'm attempting to make an async call getUsersList(), but the issue is that it's not triggering the dispatch (it's not logging "hello"). It worked ...

Cannot use a 'string' type expression to index a 'Request<ParamsDictionary, any, any, Query>' type

Currently, my goal is to develop a middleware that can validate the input data in a request. export function validator(schema: Joi.ObjectSchema, key: string) { return function (req: Request, res: Response, next: NextFunction): void { try { Joi ...

Show a nested JSON object when the specific key is not recognized

I received the following data from my API: { "id": 82, "shortname": "testing2", "fullname": "test2", "address": "addrtest2", "telephone" ...

VScode has identified potential problems with modules that utilize Angular Ivy, however, this should not cause any major issues

Encountering a problem with using Angular in VSCode, where there seems to be no ngModules due to AngularIvy. The error message indicates an issue with 'CommonModule' not being recognized as an NgModule class: [{ "resource": "[...]src/app/com ...

Tips for parsing text responses in React to generate hyperlinks and emphasize specific words

I'm currently tackling a React project and facing an interesting challenge. I have a text response that needs to be parsed in a way that all URLs are automatically turned into clickable hyperlinks (using anchor tags). Moreover, there's a requirem ...

Is there a way to include values in the body of an HTTP GET request using Angular?

I've created a function in my service that looks like this: /** * Retrieve all data * @param sendSelectedValues string */ getAllActPlanBalanceYearData(sendSelectedValues: any): Observable<any> { const url = `/yearlyvalues/act-and ...

Creating a distinct Output type in Typescript to avoid any confusion between Output arguments and Input arguments

Inspired by C#, I am looking to define the following: type FunctionOutput<T> = T; // This is a basic implementation that needs improvement type Result = {result: number}; function myFun(a: number, b: number, c: FunctionOutput<Result>) { c.r ...

The status of the Office.js appointment remains updated even after the saveAsync callback is executed

Utilizing the Office JavaScript API for an Outlook add-in, I encountered a issue with some code designed to save an appointment and close its window. Despite saving the appointment through the API, I continue to receive a "Discard changes" confirmation dia ...

Why should TypeScript interfaces be utilized in Angular services for defining type information?

What are the benefits of creating an interface for an Angular service as opposed to simply exporting the service class and using that for type information? For example: class Dashboard { constructor(ui: IUiService){} } vs class Dashboard { cons ...

Conflicting events arising between the onMouseUp and onClick functions

I have a scrollbar on my page that I want to scroll by 40px when a button is clicked. Additionally, I want the scrolling to be continuous while holding down the same button. To achieve this functionality, I implemented an onClick event for a single 40px s ...

what is the best way to eliminate comments from nested arrays when using useReducer?

Can someone help me figure out how to use useReducer and useContext to manipulate global state? I specifically need to know how to delete comments using useReducer. Data Structures View the interface image here Sample Data Array export const listsData:IDa ...