Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Typescript think my enum is undefined?

I'm using Typescript, Redux, and React, all of which are new to me so this probably has a simple fix I'm just not seeing.

I have an actions.ts file which includes an enum like this:

export enum AnimalTypes {
    CAT = 'CAT',
    DOG = 'DOG'
}

I import it in my reducers.ts file and was trying to use it in a log statement like this:

import {AnimalTypes} from './actions';

export function someFunction() {
    // Print the word "CAT"
    console.log(AnimalTypes[AnimalTypes.CAT]);
}

I get the following error when I try to launch my site:

TypeError: Cannot read property 'CAT' of undefined
  at someFunction (reducer.ts:5)
  at combineReducers.js:20
  etc.

My IDE doesn't give me any errors and neither does TSLint. I've read a bunch online trying to find the answer but the closest I came was from someone who didn't have the "export" keyword on their enum and I do.

What could be going on here? I'd be grateful for any help.

Thank you.

EDIT: It's not the reverse mapping that it's having a problem with, rather any usage of the enum. That was just the shortest usage I could think of. I'm actually using it in a switch statement:

import {AnimalTypes} from './actions';

export function otherFunction(animal) {
    switch (animal.type) {
        case AnimalTypes.CAT:
            // Do stuff
}

When I build the above code, I get this error Uncaught TypeError: Cannot read property 'CAT' of undefined

like image 874
Reagankm Avatar asked May 04 '18 21:05

Reagankm


People also ask

Why enum is not defined?

The Python "NameError: name 'Enum' is not defined" occurs when we use the Enum class without importing it first. To solve the error, import the class from the enum module before using it - from enum import Enum .

Does TypeScript support enum?

Enums are one of the few features TypeScript has which is not a type-level extension of JavaScript. Enums allow a developer to define a set of named constants. Using enums can make it easier to document intent, or create a set of distinct cases. TypeScript provides both numeric and string-based enums.

How does TypeScript enum work?

In TypeScript, enums, or enumerated types, are data structures of constant length that hold a set of constant values. Each of these constant values is known as a member of the enum. Enums are useful when setting properties or values that can only be a certain number of possible values.

Can I use TypeScript enum in JavaScript?

Enums are a feature added to JavaScript in TypeScript which makes it easier to handle named sets of constants. By default an enum is number based, starting at zero, and each option is assigned an increment by one. This is useful when the value is not important.


3 Answers

This feature of typescript is called "reverse mapping", and per the documentation it is only supported with numeric enums. Here is the snippet from https://www.typescriptlang.org/docs/handbook/enums.html:

In addition to creating an object with property names for members, numeric enums members also get a reverse mapping from enum values to enum names.

like image 62
Chris Edgington Avatar answered Oct 16 '22 09:10

Chris Edgington


I couldn't reproduce your exact case: I imported an enum in my reducer and created that exact function which logged the enum, and it worked.

However, I just ran into the same problem in a slightly different context: I added the import for my AppRoutes enum in my SideNav file. Inside the SideNav file, in a const popularArticles that mapped through some JSON and returned some TSX, when I tried to <NavLink to={AppRoutes.something}> I got "cannot read property something of undefined" even though hovering over AppRoutes.something in the IDE would show me the correct value from the correct source. I think this is a pretty similar case to yours so I hope my solution will help future readers running into this problem.

What solved it for me was to integrate the const popularArticles (which was outside the SideNav class) into a variable public popularArticles inside the class, just before the constructor. I don't know why but upon further experimentation I found that apparently you can't access the enum outside of a class or SFC...

like image 44
Henrique Saias Avatar answered Oct 16 '22 10:10

Henrique Saias


What I did was this:

import {AnimalTypes} from './actions';

export function someFunction() {
    var animalTypesEnum = AnimalTypes;
    // Print the word "CAT"
    console.log(animalTypesEnum[animalTypesEnum.CAT]);
}

and it worked. TS v3.6.4

like image 42
ihorbond Avatar answered Oct 16 '22 11:10

ihorbond