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

The licensed Angular Google Map component is failing to display the map

I've been experimenting with the new Google Map component developed by the Angular Team (from the package @angular/google-maps) with the help of this insightful tutorial. Unfortunately, I'm facing an issue where the map isn't being displaye ...

Issue with Angular2 wysiwyg component failing to submitThe Angular2

I'm currently in the process of familiarizing myself with angular2 by developing a sleek wysiwyg component. However, I seem to have reached an obstacle at this point. Below is the code I've been working on: The form that I am utilizing for testi ...

We are considering implementing Angular 2, however our current application is built with Angular 1.x. Are there any resources available for integrating Angular 2 with Angular 1.x?

Currently, rewriting our app is not an option and we are also hesitant to develop a new app solely for angular 2. We are exploring alternatives to integrate both frameworks gradually for a smoother migration process. ...

Creating tests for subscription within the onInit() method in an Angular component

In my Spinner Component class, I have implemented a functionality to show/hide Progress Spinner using Angular Material. Below is the code snippet for the class: export class SpinnerComponent implements OnInit, OnDestroy { visible = true; private s ...

Is subtyping causing issues in TypeScript's inheritance model?

I am currently utilizing TypeScript for my coding projects, and I have observed that it can allow the production of non-type-safe code. Despite implementing all the "strict" options available to me, the behavior I am experiencing goes against the principle ...

When using TypeScript, it is important to ensure that the type of the Get and Set accessors for properties returning a

Why is it necessary for TypeScript to require Get/Set accessors to have the same type? For example, if we want a property that returns a promise. module App { export interface MyInterface { foo: ng.IPromise<IStuff>; } export int ...

What could be causing the error message (No overload matches this call) to pop up when attempting to subscribe to .valueChanges() in order to retrieve data from Firestore?

Currently, I am developing an Angular application that utilizes Firebase Firestore database through the angularfire2 library. However, I am encountering a challenge. I must admit that my background is more in Java than TypeScript, so there might be some g ...

The necessity of the second parameter, inverseSide property in TypeORM's configurations, even though it is optional

As I delve into learning Typescript and TypeORM with NestJS simultaneously, a recent use-case involving the OneToMany and ManyToOne relation decorators caught my attention. It seems common practice for developers to include the OneToMany property as the se ...

Tips for getting a 'yes' or 'no' response with ngx-bootstrap modal

I have been utilizing ngx-bootstrap modal for my project, but I am considering implementing a custom confirm dialog with the following structure: confirmDialog(message: string, note: string, onOk, onCancel) { // Open modal // Perform certain actions ...

Exploring the concept of Server-Side Rendering in AngularIO

Exploring the fundamentals of SSR and AngularIO (latest version) has been quite enlightening. The distinction between CSR and SSR seems obvious based on their names. CSR carries out all the logic in the client side - for example, <app-route> remains ...

Testing abstract class methods in Jest can ensure full coverage

In my project, I have an abstract generic service class. export default abstract class GenericService<Type> implements CrudService<Type> { private readonly modifiedUrl: URL; public constructor(url: string) { this.modifiedUrl = ...

What can possibly be the reason why the HttpClient in Angular 5 is not functioning properly

I am attempting to retrieve data from the server and display it in a dropdown menu, but I am encountering an error while fetching the data. Here is my code: https://stackblitz.com/edit/angular-xsydti ngOnInit(){ console.log('init') this ...

Error: Property 'mytest' is undefined and cannot be read

While working with Swagger API, I encountered an error message when calling the endpoint stating "Cannot read property 'mytest' of undefined" class UserData { private mytest(req:any, res:any, next:any){ return res.json('test32423423&a ...

Transferring data between components in React by passing parameters through Links

When calling another component like <A x={y}/>, we can then access props.x inside component A. However, in the case of calling EditCertificate, the id needs to be passed to the component. I am using a Link here and struggling to pass the id successf ...

Generate barcodes using Angular 2

Can anyone point me in the direction of an Angular 2 Barcode Generator capable of creating code 128 barcodes? I've been searching but haven't had any luck finding one. If you have any suggestions or can offer assistance, it would be greatly appr ...

The upcoming router is not compatible with the NextPage type

I am currently working on introducing dynamic routing into an application that was originally designed with static routes. However, I am facing some confusion as I encounter TypeScript errors that are difficult for me to understand. Below is the code snipp ...

Organizing objects into arrays in Node.js

I have an array and I need to concatenate an object after the array. Here is my array: const users = [ {name: "Joe", age: 22}, {name: "Kevin", age: 24}, {name: "Peter", age: 21} ] And here is my object: ...

Angular 2 - One-Stop Form Component for Creating and Modifying

Seeking advice on how to efficiently reuse my Form Component. Data Model: class Contact { id?: String; name: String; } When a new Contact is created, the id is optional in the model as it doesn't exist at that point. When editing a Contac ...

Having trouble with @viewChild not activating the modal popup and displaying an error message stating that triggerModal is not a function in

I am facing an issue where the click event is not being triggered from the parent component to display a Bootstrap 3 modal. I am getting the following error: ERROR TypeError: this.target.triggerModal is not a function This is what I have done so far: Pa ...

Transmit information from an Angular application to a Spring Boot server using a POST request

Attempting to send JSON data from a frontend Angular project to a Spring Boot backend for the first time. Limited experience with both technologies and unsure if the HTTP POST method in Angular is incorrect, or if the backend isn't receiving the expec ...