Skip to content

Proposal: Implicitly include properties of implemented interfaces #533

@kaitlynbrown

Description

@kaitlynbrown

If an interface contains more than a few properties and is used in multiple places, you end up with a very significant amount of repetition that clutters up your schema. This means it requires a lot more scrolling to move around the schema, and the important details of a type (eg which properties are unique to it) are obscured by the noise added by all of the extra repetition.

As a contrived example, take the following currently legal schema, similar in structure to what I'm currently working on:

interface Vehicle {
  id: ID!
  make: VehicleMake
  wheelCount: Int
  acceleration: Float
  topSpeed: Float
  mass: Float
  capacity: Int
}

type Bicycle implements Vehicle {
  id: ID!
  make: BicycleMake
  wheelCount: Int
  acceleration: Float
  topSpeed: Float
  mass: Float
  capacity: Int
  gearCount: Int
}

interface Automobile implements Vehicle {
  id: ID!
  make: AutoMake
  wheelCount: Int
  acceleration: Float
  topSpeed: Float
  mass: Float
  capacity: Int
  engineCylinders: Int
  engineSize: Float
}

type Car implements Automobile {
  id: ID!
  make: CarMake
  wheelCount: Int
  acceleration: Float
  topSpeed: Float
  mass: Float
  capacity: Int
  engineCylinders: Int
  engineSize: Float
  trunkSize: Float
}

type Motorcycle implements Automobile {
  id: ID!
  make: MotorcycleMake
  class: MotorcycleClass
  wheelCount: Int
  acceleration: Float
  topSpeed: Float
  mass: Float
  capacity: Int
  engineCylinders: Int
  engineSize: Float
}

type Truck implements Automobile {
  id: ID!
  make: TruckMake
  wheelCount: Int
  acceleration: Float
  topSpeed: Float
  mass: Float
  capacity: Int
  engineCylinders: Int
  engineSize: Float
  maxLoad: Float
}

union AutoMake = CarMake | TruckMake | MotorcycleMake
union VehicleMake = AutoMake | BicycleMake

I propose that the following would be valid, and equivalent to the above:

interface Vehicle {
  id: ID!
  make: VehicleMake
  wheelCount: Int
  acceleration: Float
  topSpeed: Float
  mass: Float
  capacity: Int
}

type Bicycle implements Vehicle {
  make: BicycleMake
  gearCount: Int
}

interface Automobile implements Vehicle {
  make: AutoMake
  engineCylinders: Int
  engineSize: Float
}

type Car implements Automobile {
  make: CarMake
  trunkSize: Float
}

type Motorcycle implements Automobile {
  make: MotorcycleMake
  class: MotorcycleClass
}

type Truck implements Automobile {
  make: TruckMake
  maxLoad: Float
}

union AutoMake = CarMake | TruckMake | MotorcycleMake
union VehicleMake = AutoMake | BicycleMake

as you can see, even with this relatively simple example, we would be able to cut the number of lines of code in half. Instead of spanning multiple screens, it can now easily fit on a single screen. Each type clearly highlights the attributes which are unique to that type, and if one wants to know what other properties are included, one can easily glance up to see them (or examine the type in GraphiQL).

Furthermore, say I want to add another property to Vehicle, like say color. The way it currently is, that means I have to now remember to also add the property to Bicycle, Automobile, Car, Motorcycle and Truck. When I want to change something, the fewer places I have to make a change (and the fewer places I have to remember to change), the better. With the proposed change, I would only need to add the color property in one place to have it added to all Vehicles

Metadata

Metadata

Assignees

No one assigned

    Labels

    👻 Needs ChampionRFC Needs a champion to progress (See CONTRIBUTING.md)💭 Strawman (RFC 0)RFC Stage 0 (See CONTRIBUTING.md)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions