Traversing the enum's keys poses a challenge in terms of typing

Imagine you need to display all values of an enum

enum AnEnum {
    a = 'a',
    b = 'b'
}

const keys = Object.keys(AnEnum);

keys.forEach(key => {  
     console.log(AnEnum[key]);
});

This results in the following error message:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'typeof AnEnum'. No index signature with a parameter of type 'string' was found on type 'typeof AnEnum'

https://i.sstatic.net/nPMD6.png DEMO

The only solution I could come up with is adding any

(AnEnum as any)[key]

However, I believe there should be a better workaround. Any recommendations?

Answer №1

Exploring the functionality of Object.keys() method in TypeScript can provide insights into its typing within the standard library, as seen below:

interface ObjectConstructor {
  keys(o: object): string[];
}

The return type specified is string[]. This signifies that Object.keys(obj) yields a value of type Array<string>, rather than Array<keyof typeof obj>, where each key represents a union based on the known keys of an object. The compiler may not be able to ascertain if an object only contains the exact keys it knows about.

If attempting to access an object using a solely known string key, confirmation of having a string index signature for the object is necessary. Failure results in the compiler generating warnings and assuming the any type.


In scenarios where you are certain of an object's contained keys (e.g., a string enum without reverse mappings), employing a type assertion informs the compiler accordingly:

const keys = Object.keys(AnEnum) as Array<keyof typeof AnEnum>;

Subsequently, iterating through the loop works as intended:

keys.forEach(key => {
    console.log(AnEnum[key]); // outputs correctly
});

Note that utilizing

Object.keys(obj) as Array<keyof typeof obj>
has limitations too. If additional unknown keys exist within
obj</code}, especially with values differing from the known ones, runtime errors may occur despite successful compilation:</p>
<pre><code>interface Foo {
    a: string,
    b: string
}
const f = { a: "hello", b: "goodbye", c: 123 };
const foo: Foo = f; 

(Object.keys(foo) as Array<keyof Foo>).forEach(k => console.log(foo[k].toUpperCase()));
// Prints:
// HELLO
// GOODBYE
// 💥 RUNTIME ERROR! foo[k].toUpperCase is not a function

It is advised to exercise caution when implementing such practices!

Check out this Playground link for interactive code snippets

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

My intention is to shift the TypeScript object to a higher level within the hierarchy

Currently, I am working with TypeScript and my main goal is to transform the object structure in ①props into the structure shown in ②. ① Test {props: {…}} props: avatarUrl: "/test.jpg" id: 1 name: "test" ...

Having difficulty running lint on Vue 3 TypeScript application, but building process is successful

We are encountering an issue at the moment. We can successfully build our app, but we are facing challenges with linting using the vue tools (vue-cli-service ...). The hot-reloading feature works initially, but upon saving a file, we receive an error mess ...

Travis CI's TypeScript build process detects errors before Mocha has a chance to catch them

Instead of a bug, the TypeScript compiler is doing its job but causing my Travis builds to fail. In my package, I have a function named completeRound which accepts a number as its first argument and 3 optional arguments. Since it's in TypeScript, I s ...

How can you ensure an interface in typescript 3.0 "implements" all keys of an enum?

Imagine I have an enum called E { A = "a", B = "b"}. I want to enforce that certain interfaces or types (for clarity, let's focus on interfaces) include all the keys of E. However, I also need to specify a separate type for each field. Therefore, usi ...

Troubleshooting a TypeScript error when trying to access an imported service in Angular 2

I've been working on creating a form that allows users to input required details, which will trigger a server call and save the information. However, no matter what I try, I keep encountering the following error: ORIGINAL EXCEPTION: TypeError: this.po ...

The use of aliases is not supported by a published node module

I have a project built using create-react-app and it's utilizing react-app-rewired/react-scripts-ts. Within my tsconfig file, I've configured it as follows: baseUrl: "src", paths: { "src/*": "./*" } In many files within this project, the pa ...

Unit Testing with Angular: Testing the setValueControl function

I am currently in the process of writing unit tests for a straightforward function that assigns controls to various values. fillFormAssociazioneVeicolo() { if (this.aaa) { setValueControl( this.aaa.targaTelaio, this.form.get(&apos ...

Tips for applying personalized CSS to individual Toast notifications in Angular

MY QUESTION : I am looking to customize the CSS of a single toast used in Angular components. While there may be multiple toasts, I specifically want to style one particular toast differently. For example, the toast image can be viewed here: example toast ...

Tips for utilizing a personalized design with the sort-imports add-on in VS Code?

After recently installing the VS Code extension sort-imports, I decided to give a custom style called import-sort-style-module-alias a try. Following what seemed to be the installation instructions (via npm i import-sort-style-module-alias) and updating m ...

Jest may come across test suites, but it discreetly disregards the individual tests

Having encountered an issue with Jest testing in a Nuxt/Vue v2 project, I found that after making some changes, the tests were no longer running. The unit tests were either passing or failing initially, but suddenly stopped running altogether. ----------|- ...

Managing HTTP requests with errors within a forEach loop in Angular 9

I am currently coding a script that iterates through an array to make HTTP requests. Most of these requests are directed towards non-existent resources, but I do not have information on which ones specifically. Here is the code snippet I am using: ...

Utilizing Async/Await with Node.js for Seamless MySQL Integration

I have encountered two main issues. Implementing Async/Await in database queries Handling environment variables in pool configurations I am currently using TypeScript with Node.js and Express, and I have installed promise-mysql. However, I am open to usi ...

What is the best way to transfer data to the server in a loop without encountering synchronization issues?

I am working with an array of products in typescript (in angular) and my goal is to update their prices in the database using http calls. The way I currently insert them is as follows: array.foreach(element=>{ this.product.price=element; this.myS ...

The reference to "joiner" property cannot be found in the type "{}"

Struggling with setting state in tsx and encountering an error when trying to access JSON data. Property 'joiner' does not exist on type '{}'. TS2339 Below is the component code (trimmed for brevity) import Player from '../c ...

Leveraging jQuery within a webpack module shared across multiple components, located outside the webpack root directory

When working with multiple layouts that rely on shared typescript files, it is important to ensure these files are accessible across different layouts using webpack. While attempting to include jquery in my ajax.ts, I encountered the following error: ERR ...

Tips for monitoring the loading of data in TypeScript with observers?

One of the methods in my class is responsible for fetching information from the server: public getClassesAndSubjects(school: number, whenDate: string) { this.classService.GetClassesAndSubjects(school, whenDate).subscribe(data => { if (!data.h ...

Typescript encounters Duplicate error when method overloading is implemented

Below is the code snippet that I am working with: public async insert(data: iFlower | iFlower[]): Promise<iFlower> | Promise<iFlower[]> { await this.insert(data); } private async insert(data: iFlower): Promise<iFlower>{ .... return d ...

Updated the application to Angular 6 but encountered errors when attempting to run npm run build --prod. However, running the command npm run build --env=prod was executed without any issues

Running the command npm run build -- --prod results in the following error messages: 'PropertyName1' is private and can only be accessed within the 'AppComponent' class 'PropertyName2' does not exist in type 'AppCompo ...

What is the process for defining custom properties for RequestHandler in Express.js middleware functions?

In my express application, I have implemented an error handling middleware that handles errors as follows: export const errorMiddleware = (app: Application): void => { // If the route is not correct app.use(((req, res, next): void => { const ...

Activate the drop-down menu in Angular 6 by hovering over it with your mouse

I am just beginning my journey with Angular 6 and Bootstrap. Currently, I am working on a Navigation bar that consists of 3 navigation items. One of the nav items is called "Store", and when a user hovers their mouse over it, I want to display a mega menu ...