Share common fields between Input and Type in GraphQL
Asked Answered
C

1

12

I was wondering if there's a way to share the common fields between Input and Type in GraphQL so that I don't have to define the same set of fields in multiple places.

Example:

input PersonInput {
    id: String!
    name: String
    address: String
}

type Person {
    id: String!
    name: String
    address: String
}

I know Fragment might be a solution, but if my understanding is correct, using Fragment always requires you to put an ON condition which makes it look like this:

Fragment PersonCommonFields on Person {
    ...
}

There seems to be no way to specify "on Person/PersonInput".

Canthus answered 30/8, 2018 at 16:10 Comment(1)
I've asked the same question, and it got a good answer here before being closed as a duplicate.Arni
S
11

GraphQL fragments are for querying, not schema definition.

When I started learning GraphQL I was annoyed by this too because I was still thinking RESTfully. In most cases having the freedom to set certain fields non-nullable or remove them entirely from an input/output type is invaluable.

e.g.

input CreatePersonInput {
  name: String!
  slug: String
  address: String
}

type Person {
  id: ID! # Autogenerated on the server
  name: String!
  slug: String! # Will always exist, either user provided or computed
  # address: String # Omitted for security reasons
}

It may seem like a lot of extra code at first, but the flexibility this brings you over resource based schemas is worth it for long-term projects. I've seen it help out dozens of times.

You should also consider behavior/task-based mutations over resource or "anemic mutations"

I highly recommend learning about fat queries and read about Relay Specification. Even if you don't end up wanting Relay on the client, following some of their rules can really clear up common misconceptions about GraphQL.

Sparklesparkler answered 30/8, 2018 at 16:39 Comment(1)
still a weird decision on graphql's part imo. Let users separate it if they choose, but users should still have the freedom to reuse the same type. For example, what if I defined a type FullName { firstName: String, lastName: String }. Why should I have to define a seaprate FullNameInput? Not to mention, the primitive types String and Boolean and Int don't have corresponding StringInput, BooleanInput`, etc, so they clearly understand that in same cases reuse is fine...Kerb

© 2022 - 2024 — McMap. All rights reserved.