norr
norr

Reputation: 2167

Maping type keys from enum values

I have long enum like that:

enum Vegetable {
  TOMATO
  POTATO
  ONION
  # ...and many more
}

and type

type VegetableInfo {
  isRed: Boolean!
  bbb: Int!
  ccc: String!
}

Now I want to provide frontend all vegetables info.

I could just return array of vegetables:

type Query {
  vegetables: [Vegetable]!
}

But since it will be indexed array and not associative, in frontend JS I will be NOT able to quickly access data for needed vegetable like so:

vegetables.tomato.isRed // true
// or maybe
vegetables.TOMATO.isRed // true

Instead I will be forced to write some search function to check if tomato exists in any item. I need associative array (object with keys) instead.

I can easy achieve this by doing this:

type Query {
  vegetables: VegetablesInfo!
}

enum Vegetable {
  TOMATO
  POTATO
  ONION
  # ...and many more
}

type VegetablesInfo {
  TOMATO: VegetableInfo!
  POTATO: VegetableInfo!
  ONION: VegetableInfo!
  # ...and many more
}

type VegetableInfo {
  isRed: Boolean!
  bbb: Int!
  ccc: String!
}

But enum is not even used here. I still need that enum in other parts of graphql. I will have to repeat every vgetable name in both places, so it's bad.

I cannot find any way to generate type keys from enum. Code below will not work, but is there something like this?

type VegetablesInfo {
  ...Vegetable: VegetableInfo!
}

Upvotes: 1

Views: 605

Answers (1)

fedonev
fedonev

Reputation: 25659

GraphQL spec: The target field of a field selection must be defined on the scoped type of the selection set.

In plain English, no, you can't "dynamically" define fields. Types can only have explicitly defined fields. As you say, the practical solution is to return a list of VegetableInfo (adding a name: Vegetable field) to the client. The client can trivially filter the list for the target Vegetable by name:

// client.ts
const vegFinder = (name: Vegetable, vegetables: VegetableInfo[]): VegetableInfo | undefined  => {
    return vegetables.find((veg) => veg.name === name)
} 

Upvotes: 2

Related Questions