Defining array of enum type in Typescript

I have created a Typescript DTO, where I want to ensure type safety for a list of strings (which are derived from an enum type.



export class ConnectedUserWithPhotosDTO extends UserWithPhotosDTO {
  userTags: keyof User["userTags"][]

  constructor(user: User, photos: ResponsePhotoDTO[]) {
    super(user, photos)
    console.log(user.userTags)
    this.userTags = user.userTags;
  }
}

The typescript compiler complains about the following error:

Type 'UserTags[]' is not assignable to type 'number | keyof UserTags[][]'.

apparently, the value of userTags evaluates to

number | keyof UserTags[][]

Here is the enum definition that i am defining.

export enum UserTags {
  FITNESS = 'Fitness',
  FOURTWENTY_FRIENDLY = '420 Friendly',
  MEDITATION = 'Meditation',
  DRINKS = 'Drinks',
  DOGS = 'Dogs',
  CATS = 'Cats',
  FASHION = 'Fashion',
  WINE_TASTING = 'Wine Tasting',
  FOODIE = 'Foodie',
  ART = 'Art',
  PARTYING = 'Partying',
  TRAVELIING = 'Travelling',
  GAMING = 'Gaming',
}

Inside the User class the UserTags is defined as:

 @ApiProperty({ enum: UserTags, isArray: true, default: [] })
  @Column('enum', { enum: UserTags, array: true, nullable: true, default: [] })
  userTags: UserTags[]

how can I define just the type of keyof for the specific Enum value?

Upvotes: 3

Views: 9588

Answers (3)

Linda Paiste
Linda Paiste

Reputation: 42188

Your post is a bit confusing because of your use of keyof. It's unclear whether you want the enum keys "FITNESS", etc. or the enum values "Fitness", etc.

It's clear based on the code of the User and your error message that what you are getting when you access user.userTags is the values. The type of the values is just the enum itself, so you would want

userTags: UserTags[]

just like what you have in the User. It makes sense that this would match the type in User since we are setting the userTags property based on User["userTags"].


Let's break down the type keyof User["userTags"][] that you tried and see what it really means.

User["userTags"] gives us the userTags property of the User type. We can see from your User code that User["userTags"] is UserTags[]. That is an array of the values from the UserTags enum. So something like ["Fitness", "Fashion"].

User["userTags"][] means that we want an array of these. But it's already an array, so you are now asking for an array of arrays of enum values: UserTags[][]. Which would be [["Fitness"], ["Fashion", "Foodie"]].

keyof User["userTags"][] means that we now want the keys of that array of arrays: keyof UserTags[][]. The key of an array is a number so typescript gives you number | keyof UserTags[][]. (I'm not sure why it isn't just number).


Perhaps you were trying to get the keys for the UserTags enum object? keyof typeof UserTags will give you the union type "FITNESS" | "FOURTWENTY_FRIENDLY" | "MEDITATION" .... But it doesn't seem like that's what you actually want to use. You want the union of the enum values which is just UserTags.

Upvotes: 1

Andrei Tătar
Andrei Tătar

Reputation: 8295

You can also do something like:

const userTags: User['userTags'];

Upvotes: 2

Timothy
Timothy

Reputation: 3593

Assuming that UserTags is enum. Its something like

userTags: Array<keyof typeof UserTags>

Upvotes: 7

Related Questions