Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why Does Typescript not Recognize Enum Members as Valid Properties When Using [key in enum] Index Signature

I’m working on a TypeScript project and I’m running into a strange issue when using enum members as indexed keys for an interface. Both my enum and interface are declared in global .d.ts files (no imports or exports).

// enums.d.ts
...
enum ItemFlag {
  IsPushable = "isPushable",
  IsTakable = "isTakable",
  IsUnique = "isUnique"
}
...

// interfaces.d.ts
...
interface IThingProps {
  id: string;
  name: string;
}

interface IItemProps extends IThingProps {
  [key in ItemFlag]?: boolean;
}
...

However, when I try to create an object which implements the IItemProps interface:

const props: IItemProps = {
  id: "item_small_cup",
  name: "small cup",
  [ItemFlag.IsTakable]: true
};

I get the following error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

"Type ‘{ id: string; name: string; isTakable: boolean; }’ is not assignable to type ‘IItemProps’.
Object literal may only specify known properties, and ‘[ItemFlag.IsTakable]’ does not exist in type ‘IItemProps’."

What’s odd is I’m doing this with another enum and it’s working fine. The only difference is I’m declaring the type of the object using it inline like:

const genders: {[key in Gender]: Pronouns; } = {
  [Gender.It]: {
    they: "it",
    them: "it",
    // You get the idea
  }
}

I suppose this example also doesn’t have the property as optional, but removing the optional ‘?’ from the index signature for ItemFlag doesn’t change the error at all.

Any insight as to this weird, inconsistant behavior?

>Solution :

Try using types instead of interface:


enum ItemFlag {
  IsPushable = "isPushable",
  IsTakable = "isTakable",
  IsUnique = "isUnique"
}

type IThingProps =  {
  id: string;
  name: string;
}

type IItemProps  = IThingProps & {
  [key in ItemFlag]?: boolean;
}

const props: IItemProps = {
  id: "item_small_cup",
  name: "small cup",
  [ItemFlag.IsTakable]: true
};

What you’re trying to build is a Mapped Type and typescript does not support mapped interfaces. Or at least you will not be able to define a concrete property/method on to interfaces.

As a general rule of thumb, I use types unless an interface is required.

Here’s a helpful answer which describes the difference between the two.

https://stackoverflow.com/a/54101543/2703813

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading