GraphQL如何避免输入和输出类型之间的重复代码

弗雷德·梅里奥特

我是GraphQL的新手,但我真的很喜欢。现在,我正在使用接口和联合,现在我面临着突变问题。

假设我有这个架构:

interface FoodType {
    id: String
    type: String
    composition: [Ingredient]
  }

  type Pizza implements FoodType {
    id: String
    type: String
    pizzaType: String
    toppings: [String]
    size: String
    composition: [Ingredient]
  }

  type Salad implements FoodType {
    id: String
    type: String
    vegetarian: Boolean
    dressing: Boolean
    composition: [Ingredient]
  }

  type BasicFood implements FoodType {
    id: String
    type: String
    composition: [Ingredient]
  }

  type Ingredient {
      name: String
      qty: Float
      units: String
  }

现在,我想创建新的食物,所以我开始做这样的事情:

type Mutation {
    addPizza(input:Pizza):FoodType
    addSalad(input:Salad):FoodType
    addBasic(input:BasicFood):FoodType
}

由于两个原因,此操作不起作用:

  1. 如果我想将一个对象作为参数传递,则该对象必须是“输入”类型。但是“ Pizza”,“ Salad”和“ BasicFood”只是“类型”。
  2. 输入类型不能实现接口。

因此,我需要像这样修改以前的架构:

interface FoodType {
    id: String
    type: String
    composition: [Ingredient]
}

type Pizza implements FoodType {
    id: String
    type: String
    pizzaType: String
    toppings: [String]
    size: String
    composition: [Ingredient]
}

type Salad implements FoodType {
    id: String
    type: String
    vegetarian: Boolean
    dressing: Boolean
    composition: [Ingredient]
}

type BasicFood implements FoodType {
    id: String
    type: String
    composition: [Ingredient]
}

type Ingredient {
        name: String
        qty: Float
        units: String
}

type Mutation {
    addPizza(input: PizzaInput): FoodType
    addSalad(input: SaladInput): FoodType
    addBasic(input: BasicInput): FoodType    
}

input PizzaInput {
    type: String
    pizzaType: String
    toppings: [String]
    size: String
    composition: [IngredientInput]
}

input SaladInput {
    type: String
    vegetarian: Boolean
    dressing: Boolean
    composition: [IngredientInput]
}

input BasicFoodInput {
    type: String
    composition: [IngredientInput]
}

input IngredientInput {
        name: String
        qty: Float
        units: String
}

因此,在这里,我定义了我的3种制作披萨,色拉和基本食物的方法。我需要定义3种输入类型(每种食物一种),并且还需要为“成分”定义一种新的输入类型。

重复很多。那样你觉得可以吗?还是有更好的方法来解决这个问题?

谢谢

丹尼尔·雷登(Daniel Rearden)

可以做很多事情。例如,如果您要以编程方式声明架构,则可以避免如下所示:

const getPizzaFields = (isInput = false) => {
  const fields = {
    type: { type: GraphQLString }
    pizzaType: { type: GraphQLString }
    toppings: { type: new GraphQLList(GraphQLString) }
    size: { type: GraphQLString }
    composition: {
      type: isInput ? new GraphQLList(IngredientInput) : new GraphQLList(Ingredient)
    }
  }
  if (!isInput) fields.id = { type: GraphQLString }
  return fields
}

const Pizza = new GraphQLObjectType({
  name: 'Pizza',
  fields: () => getFields()
})

const PizzaInput = new GraphQLObjectType({
  name: 'Pizza',
  fields: () => getFields(true)
})

或者,如果您的对象/输入遵循类似的模式,则您甚至可以编写一个用于从类型生成输入的函数:

const transformObject = (type) => {
  const input = Object.assign({}, type)
  input.fields.composition.type = new GraphQLList(IngredientInput)
  delete input.fields.id
  return input
}

另外,在使用定义架构时makeExecutableSchema,您可以执行以下操作:

const commonPizzaFields = `
    type: String
    pizzaType: String
    toppings: [String]
    size: String
`

const schema = `
  type Pizza {
    id: String
    ${commonPizzaFields}
    composition: [Ingredient]
  }

  input PizzaInput {
    ${commonPizzaFields}
    composition: [IngredientInput]
  }
`

所有这些方法的问题在于,尽管从技术上讲它们可能使您的代码更干燥,但它们也降低了模式的可读性,我认为这比复制本身更容易出错。

同样重要的是要理解,虽然从语法上讲,类型和输入类型可能看起来相同,但从功能上来看却不一样。例如,类型上的字段可能具有参数:

type Pizza {
  toppings(filter: ToppingTypeEnum): [String]
}

输入类型字段没有参数,因此对于类型及其对应的输入类型中toppings字段,您将无法使用相同的语法PizzaPizzaInput

就个人而言,我会咬紧牙关,只写出您已经完成的类型和输入。我唯一会做的不同的事情是将它们分组在一起(列出您的类型而不是输入),以便可以轻松发现两者之间的任何差异。但是你的里程可能非常:)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Java:如何避免在display()和write(pdf)之间重复代码

避免在“子类型”之间重复代码

如何避免关于原始类型的代码重复?

如何在C#流和Python脚本之间重复传递输入和输出?

如何避免重复输入

如何避免代码重复?

如何编辑基于输入分别显示结果的代码,并避免重复

验证多个输入字段时如何避免重复代码?

由原始类型引起的代码重复:如何避免精神错乱?

如何避免语法上相同的const和语义上不相同的非const函数之间的代码重复

使用带有标准输入和标准输出重定向的 2 进程管道时如何避免标准输入上的重复输入

CQRS如何避免在命令和事件之间重复字段?

如何避免使用php和mysql重复代码

如何避免单独输入和输出队列的竞争条件?

如何避免这种代码重复?

如何避免此代码重复?

如何避免片段代码重复?

当输入更改接收消息的类型时,避免在“接收”中重复代码

如何避免在Java和本机C ++代码之间复制数据

使用运行时类型开关(和模板化函数)避免代码重复

我如何分辨+的输入和输出之间的区别?

VHDL输入和输出代码

C#避免装箱和重复代码

避免在“ then”和“ catch”中重复相同的代码

避免在wcf和ef中的代码重复

Widget和CupertinoWidget:避免代码重复

处理递归和类型时如何减少代码重复

如何避免循环在Ruby中重复输出

如何避免 Rails Sidekiq 调度作业和工作人员使用相同代码的代码重复