Может ли тип ввода GraphQL наследовать другой тип или интерфейс?

Можно ли использовать наследование с использованием типов ввода GraphQL?

Что-то вроде этого (это, конечно, не работает с типами ввода):

interface UserInputInterface {
  firstName: String
  lastName: String
}

input UserInput implements UserInputInterface {
  password: String!
}

input UserChangesInput implements UserInputInterface {
  id: ID!
  password: String
}

Ответ 1

Нет, спецификация не позволяет типам ввода реализовывать интерфейсы. А система типов GraphQL в целом не определяет какую-либо форму наследования (ключевое слово extends добавляет поля к существующему типу и не для наследования). Даже интерфейсы не могут наследовать другие интерфейсы (хотя это кажется из-за изменений). Спецификация намеренно ограничена, чтобы оставаться простой. Это означает, что вы застряли в повторяющихся полях разных типов ввода.

Тем не менее, в зависимости от того, как вы строите свою схему, вы можете создать некий преобразователь типов, который программно добавляет общие поля на основе некоторых метаданных, например, директива.

Более того, вы можете решить свою проблему с помощью композиции (всегда помните композиция над наследованием). Э.Г.

input Name {
  firstName: String
  lastName: String
}

input UserInput {
  name: Name
  password: String!
}

input UserChangesInput {
  name: Name
  id: ID!
  password: String
}

Теперь клиент должен отправить объект на более глубокий уровень, но это не похоже на большую цену за избежание больших повторяющихся кусков. На самом деле это может быть полезно и для клиента, поскольку теперь он может иметь общую логику для построения имен, независимо от того, использует ли их запрос/мутация.

В этом примере, где есть только 2 простых поля, этот подход является излишним, но в целом - я бы сказал, что это путь.

Ответ 2

Начиная с июньской стабильной версии спецификации GraphQL тип входного объекта может расширять другой тип входного объекта:

Расширения типа входного объекта используются для представления типа входного объекта, который был расширен от некоторого исходного типа входного объекта.

Это не наследство как таковое; Вы можете только расширять базовый тип, но не создавать новые типы на его основе:

extend input MyInput {
  NewField: String
}

Обратите внимание, что нет имени для нового типа; существующий тип MyInput расширен.

Ссылочная реализация JavaScript реализовала расширения входных объектов в GraphQL.js v14 (июнь 2018 г.), хотя неясно, как на самом деле передавать расширенные поля ввода в запрос без получения ошибки.

Фактическое наследование типов см. В библиотеке graphql-s2s.