What is the best method to locate an element<T> within an Array[T] when <T> is an enum?

I've recently started learning TypeScript and exploring its functionalities. I could use some assistance in deepening my understanding.

Within our angular2 application, we have defined an enum for privileges as follows:

export enum UserPrivileges{
  SUPER,
  USER,
  GUEST 
}

We utilize this type in a function definition where it is represented as an array of the enum type:

checkPrivileges(userPrivileges: UserPrivileges[]) {...}

The approach we have taken to determine user privileges is:

this.isSuperUser = userPrivileges.includes(UserPrivileges[UserPrivileges.SUPER]);

Issue

TypeScript raises an error stating that "Argument of type 'string' is not assignable to type 'UserPrivileges'" due to the use of the Array.prorotype.includes() method call (similar issue with .indexOf().)

I have attempted various forms of explicit casting without success:

this.isSuperUser = userPrivileges.includes(<string>UserPrivileges[UserPrivileges.SUPER]);
this.isSuperUser = userPrivileges.includes(UserPrivileges[UserPrivileges.<string>SUPER]);

We managed to bypass the TypeScript error by modifying the function signature to:

checkPrivileges(userPrivileges: string[]) {...}

...but this defeats the purpose of utilizing types.

This seems like a common scenario, but perhaps there's a necessary decorator or method I'm overlooking? Is there something that needs to be added to the enum type definition to allow it to be interpreted as a string?

Edit

To clarify, our backend sends privilege tokens as strings in an array, such as

userPrivileges = ["SUPER", "GUEST", "USER"]
. The UserPrivileges enum type was intended to mirror this structure.

The old method, which functioned correctly (expecting true):

userPrivileges.indexOf(UserPrivileges[UserPrivileges.SUPER]) > -1;

Because

  • UserPrivileges.SUPER equates to 0 (due to the emitted JS explanation)
  • UserPrivileges[0]</code then results in the string <code>"SUPER"
  • ...which matches a value in userPrivileges[] from the backend.

However, these will both inaccurately (yet expectedly) return false

userPrivileges.includes(UserPrivileges.SUPER);
userPrivileges.indexOf(UserPrivileges.SUPER) > -1;

for the same reasons explained above: the server-provided userPrivileges[] does not contain a value of 0.

"Using an enum value on itself will yield back the string." In order for the suggested solution to function properly, it appears that I would need to employ the type's numeric index UserPrivileges[0] to retrieve the corresponding string for comparison with the API response?

Answer №1

Instead of

UserPrivileges[UserPrivileges.SUPER]
, try using UserPrivileges.SUPER

this.isSuperUser = userPrivileges.includes(UserPrivileges.SUPER);

In TypeScript, non-const enums can map both string values to numerical values and vice versa. In JavaScript, it would look something like this:

const UserPrivileges = {
    ['SUPER']: 0,
    ['USER']: 1,
    ['GUEST']: 2,
    [0]: 'SUPER',
    [1]: 'USER',
    [2]: 'GUEST',
}

When you pass an enum value back into itself, you will receive the corresponding string. This explains why you are encountering an error when using UserPrivileges.SUPER, as it resolves to 0 which is interpreted as a string name.


Additional information has been included in this update.

To clarify, our backend returns privilege tokens as strings in an array, for example:

userPrivileges = ["SUPER", "GUEST", "USER"]

If this is the case, it seems that userPrivileges is not an Array<T extends Enum> but rather an Array<string>.

You have a couple of options at this point. You can choose to work with strings and define UserPrivileges as

const UserPrivileges = {
    ['SUPER']: 'SUPER',
    ['USER']: 'USER',
    ['GUEST']: 'GUEST',
}

Alternatively, you could convert the list of strings to a true list of enums. Operating from that list should then function as expected.

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

Having trouble compiling Typescript code when attempting to apply material-ui withStyles function

I have the following dependencies: "@material-ui/core": "3.5.1", "react": "16.4.0", "typescript": "2.6.1" Currently, I am attempting to recreate the material-ui demo for SimpleListMenu. However, I am encountering one final compile error that is proving ...

Determining when to include @types/packagename in React Native's dev dependencies for a specific package

Just getting started with React Native using typescript. Take the package vector icon for example, we need to include 2 dependencies: 1. "react-native-vector-icons": "^7.1.0" (as a dependency) 2. "@types/react-native-vector-icons": "^6.4.6" (as a dev ...

Incorporating an alternate object array to update an array of objects: A

There are two object arrays, the main array and the temp array. The goal is to compare the main array with the temp array and update the values in the main array based on matching IDs. In this example, IDs 2 and 3 match in both arrays. Therefore, the valu ...

Personalized ornamentation using TypeScript

Is there a way to access the variables of the class when using a decorator? @ExampleDecorator() export class UserController { private userData: string = "example"; } export const ExampleDecorator = (config: IConfigSettings) => (target: Object) =&g ...

Checkbox selection can alternate based on conditions for formgroup controls

My FormGroup named 'fruits' has been set up fruits: FormGroup = formBuilder.group({ numberOfFruits: [0,Validators.min(0)], apple: false, mangoes: false }); Here is the corresponding HTML code: <div formGroupName ...

Avoiding caching of GET requests in Angular 2 for Internet Explorer 11

My rest endpoint successfully returns a list when calling GET, and I can also use POST to add new items or DELETE to remove them. This functionality is working perfectly in Firefox and Chrome, with the additional note that POST and DELETE also work in IE ...

When I pass an array of objects to Firefox (using TypeScript) and retrieve the data, I find that I am unable to retrieve it in the form of an array of objects

When it comes to saving and retrieving data from a Firebase database, I seem to be encountering an issue where the type of data retrieved does not match what I am expecting. Let me break down what I am doing and the problem I am facing: Saving data To sa ...

typescript class that utilizes a function with multiple shapes (overloading) and generics

TYPESCRIPT playground Is there a concept similar to Overloads for classes? I encountered an issue with the creation of createRequest.ts and the function should be error-free. I am looking to apply the same generics used in the createRequest function to th ...

Typescript service wrapper class returning Axios HEAD request

I am attempting to retrieve the header response using a custom Axios HTTP service wrapper. axiosClass.ts import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios"; class Http { private instance: AxiosInstance | null = n ...

Angular | The parameter type 'User[]' is incompatible with the expected parameter type 'Expected<User>' and cannot be assigned

While testing Angular, I encountered this error that has me stumped. The issue seems to be with the user inside the toBe() function. This error is occurring in the file user.service.spec.ts it('should call getUsersById', () => { const user ...

Is it recommended to store SCSS and TypeScript files in the wwwroot folder in ASP.NET Core and Angular 2 development?

I'm struggling to understand where I should place my ts and scss files. The wwwroot folder is specifically for static files, but the ts and scss files are compiled. Should I recreate a similar folder structure both in wwwroot and outside of it, and th ...

Guide to forming an array by extracting specific properties from a nested JSON array using javascript

Currently, I have this list: list = { id: 1, arr: [ {index : 1 , description: "lol" , author: "Arthur"}, {index : 2 , description: "sdadsa" , author: "Bob"}, {index : 3 , desc ...

Why is TypeScript giving an error about an undefined object key, even though the key was assigned a value in the previous command?

type MaybeThereIsAValue = { [p: string]: string | undefined } ... let bar: MaybeThereIsAValue = {}; const key = "carpe"; bar[key] = "diem"; const why = bar[key]; // why is string | undefined I am confused as to why why is showing ...

Challenges with inferring return values in Typescript generics

I'm encountering an issue with TypeScript that I'm not sure if it's a bug or an unsupported feature. Here is a Minimal Viable Example (MVE) of the problem: interface ColumnOptions<R> { valueFormatter(params: R): string; valueGette ...

The triggering of routing in Next.js is not established by useEffect

I'm facing an issue with my Next.js dynamic page that uses routing based on steps in the state. The route is supposed to change whenever a step value changes, like from null to "next" or back. However, the useEffect hook doesn't seem to be reacti ...

What is the best way to refine React Component's props with Typescript?

My setup involves utilizing two specific components: Test and Subtest. The main functionality of the Test component is to provide visual enhancements and pass a portion of its props down to the Subtest component. Some props in the Subtest component are des ...

Customizing TinyMCE's font style menu options

Our platform utilizes TinyMCE as in-place editors to allow users to make live edits to content. However, a challenge arises when using a dark background with light text, as TinyMCE defaults to using this text color rather than black. (Please note: the the ...

Tips on updating the datepicker format to be dd/mm/yyyy in ngbdatepicker

I am currently using ng-bootstrap for a datepicker and need to change the date format from yyyy/mm/dd to dd/mm/yyyy. I have tried to make this adjustment but haven't had success. If anyone has suggestions on how to accomplish this, please help. Here ...

In Angular 16, allow only the row that corresponds to the clicked EDIT button to remain enabled, while disabling

Exploring Angular and seeking guidance on a specific task. I currently have a table structured like this: https://i.stack.imgur.com/0u5GX.png This code is used to populate the table: <tbody> <tr *ngFor="let cus of customers;" [ngClass ...

Tips for utilizing ng class within a loop

Having some trouble with my template that loops through a JSON file using json server. The issue I'm facing is related to correctly applying ng class when clicking on icons. Currently, when I click on an icon, it adds a SCSS class but applies it to al ...