Home > Mobile >  Why Does Typescript not Recognize Enum Members as Valid Properties When Using [key in enum] Index Si
Why Does Typescript not Recognize Enum Members as Valid Properties When Using [key in enum] Index Si

Time:05-05

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:

"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?

CodePudding user response:

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

  • Related