What is the best way to filter by enum value in Typescript?

If I define an enum as follows:

export enum Status {
    InProgress = 0,
    Completed = 1,
    Cancelled = 2
}

and have a class that references the enum:

import { Status } from "./Status";
export class TaskDto {
  public name: string = null;
  public currentStatus: Status = null;
}
export default TaskDto;

I am encountering an issue where filtering based on the currentStatus property of TaskDto is not yielding any results.

//...some code to fetch data
let activeTasks = response.data.activeTasks as TaskDto[]; //correctly casts to an array of 4 items
let filteredTasks = activeTasks.filter(
  t => t.currentStatus === Status.Completed
);
//filteredTasks is empty when it should contain all 4 items

To workaround this issue, I converted the enum value to a string for comparison, although I feel this should not be necessary in TypeScript.

let filtered = filteredTasks.filter(
  t =>
    t.currentStatus.toString() === Status[Status.Completed]
);

Answer №1

It appears that the issue stemmed from how the server was transmitting the data back. The value of currentState for each GroceryDto was being sent as a string. Making the necessary adjustments to the enum definition, as suggested by @Aleksey, resolved the issue:

export enum Status {            
        Inactive = "Inactive",
        Active = "Active",
        Pending = "Pending"
    }

Answer №2

It's important to note that enum usage in TypeScript can be a bit tricky, as they are often misunderstood and can be used either as string-based or numeric-based types.

If you utilize your enum like this:

State.OnShoppingListUnchecked

It will be treated as a number and compared to the numeric value of 1. However, consider the following nested enum code:

a === State['OnShoppingListUnchecked'] // compare to 1
a === State[State['OnShoppingListUnchecked']] // compare to 'OnShoppingListUnchecked' string
a === State[State[State['OnShoppingListUnchecked']]] // Once again against numeric 1
// ... and so on 

If you are receiving a string from the server instead of a number, your comparisons may fail. You can automate this check by doing the following:

let toCompare = 1 // Value to compare against
if (typeof(compareValue) === 'number') {
  return State[toCompare] === compareValue // Compare number to number
} else if (typeof(compareValue) === 'string') {
  return State[State[toCompare]] === compareValue // Compare input string to string representation of enum
}

This ensures that regardless of whether the input is a string or number, you are comparing it against the correct enum entry.

String-based enums have been supported since TypeScript 2.4 and above, but in my opinion, their usage should be limited. Number-based enums provide an easy way to access additional information from array-like structures, which is not possible with string-based enums:

enum NamesEnum {
    NAME0 = 0,
    NAME1 = 1
};

namesToDisplay: string[] = [
  'Name1 display value',
  'Name2 display value'
];

let enumVal = someFunctionThatGetsEnum(); // Only works for number-based enums
this.currentDisplay = this.namesToDisplay[enumVal];

In the template:

<p>{{ currentDisplay }} </p>

If you don't need to index arrays using enums, you can replace string-based enums with String Literal Types, which offer similar benefits without as much concern for type and compatibility issues.

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

transform array elements into an object

I encountered the following code snippet: const calcRowCssClasses = (<string[]>context.dataItem.cssClasses).map( (cssClass) => { return { [cssClass]: true }; } ); This code block generates an array of objects like ...

Establish a reactive form upon data completion (asynchronously) in Angular version 5

I've been encountering an issue with updating form values post fetching data from an API. I attempted to utilize the *ngIf technique, but unfortunately, the form remains invisible even though it is properly set. Although I cannot provide the entire p ...

Error in Protractor Typescript: The 'By' type does not share any properties with the 'Locator' type

https://i.stack.imgur.com/8j2PR.png All the different versions Error. Protractor version : 5.2.0 npm : 3.10.10 node :6.9.5 typescript :2.6.0 The 'By' type does not share any properties with the 'Locator' type What is the solution to ...

Develop an interface in TypeScript for intricate data structures

Displayed below is a variable that contains a collection of objects: scenes = { sky: { image: 'assets/1.jpg', points: { blue_area: { x: 1, y: 2 }, } }, blue_area: { image: & ...

Verify if the keys are present within the object and also confirm if they contain a value

How can we verify keys and compare them to the data object? If one or more keys from the keys array do not exist in the object data, or if a key exists but its value is empty, null, or undefined, then return false; otherwise, return true. For example, if ...

Troubleshooting why the Angular innerHTML function is failing to render the specified

I'm encountering this problem where I am receiving a string const str = '<p>Please ensure Process Model diagram represents Functions adequately (boxes that represent an activity or group of activities that produce an outcome):</p>< ...

Utilize ngx-translate with an array as interpolation values

When working with ngx-translate, I use the instant method to translate messages into the user's language. These messages are provided as JSON objects and some of them contain dynamic values: { "message.key": "First value is {{0}} and se ...

A comprehensive guide on constructing a literal object in Typescript by combining an array with an object

Recently, I came across this Typescript code snippet: type SortedList = T[] & {_brand: "sorted" }; function binarySearch<T>(xs: SortedList<T>, x: T): boolean let low = 0; let high = xs.length - 1; while (high ...

What is the best way to loop through a formarray and assign its values to a different array in TypeScript?

Within my form, I have a FormArray with a string parameter called "Foo". In an attempt to access it, I wrote: let formArray = this.form.get("Foo") as FormArray; let formArrayValues: {Foo: string}[]; //this data will be incorporated into the TypeScript mod ...

I am interested in using a loop in Angular to highlight my div element

Enhancing my comprehension regarding the mentioned images. If I don't select anything within the div property, the default style (css) should appear like this, at least when one div is selected. However, the issue arises when unable to select. This ...

Analyzing elements within an array using Angular 4

I have an array filled with various Objects such as: [ {"id":1,"host":"localhost","filesize":73,"fileage":"2018-01-26 09:26:40"}, {"id":2,"host":"localhost","filesize":21,"fileage":"2018-01-26 09:26:32"}, {...} ] These objects are displayed in the fol ...

How to prevent unnecessary new instances from being created by the Inject() function in Angular

Can someone please clarify if the inject() function provides different instances of a service? I suspect this might be why my code is not functioning as expected. Let's examine the code snippet below: { path: 'recipes', comp ...

Experiencing difficulties with a click event function for displaying or hiding content

Struggling with implementing an onClick function for my two dynamically created components. Currently, when I click on any index in the first component, all content is displayed. What I want is to show only the corresponding index in the second component ...

A guide on iterating through a JSON object fetched using Http in Angular 2/Typescript

I am attempting to extract specific data from my JSON file using http. The structure of the JSON is as follows: [{"name":"Name1","perc":33},{"name":"Name2","perc":22},{"name":"Name3","perc":41}] To loop through this retrieved object, I use the following ...

React Typescript Context state isn't refreshing properly

Struggling to modify my context state, I feel like I'm overlooking something as I've worked with context in the past. The challenge lies in changing the 'isOpen' property within the context. You can view my code here: CodeSand **app.ts ...

The 'posts' binding element is assumed to have a type of 'any' by default

Currently, I'm working on a code project that involves graphql, react, and typescript. In the middle of the process, I encountered an error message stating "Binding element 'posts' implicitly has an 'any' type." I am unsure about w ...

Mastering the Type Model on Firestore Function to Retrieve Field ValuesUnlock the potential of the Type

When retrieving data from Firestore, I am able to print the entire object using doc.data. However, I am having trouble accessing the specific value of unixtime as it is coming through as undefined. I need help in correctly applying my type model so that I ...

Mastering Angular Service Calls in TypeScript: A Comprehensive Guide

In the midst of my TypeScript angular project, I am aiming to revamp it by incorporating services. However, I have encountered an issue where when calling a function within the service, the runtime does not recognize it as the service class but rather the ...

Oops! There seems to be an issue with the code: "TypeError: this

I am just starting out with Angular. Currently, I need to assign a method to my paginator.getRangeLabel (I want to use either a standard label or a suffixed one depending on certain conditions): this.paginator._intl.getRangeLabel = this.getLabel; The cod ...

When exporting an enum in StencilJS with TypeScript, the error "Cannot find name..." may occur

Looking for a solution: https://github.com/napolev/stencil-cannot-find-name In this project, there are two main files to consider: custom-container.tsx import { Component, Element, State } from '@stencil/core'; @Component({ tag: 'cu ...