Skip to content

Instantly share code, notes, and snippets.

@RobertFischer
Last active August 20, 2019 10:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RobertFischer/f165dc336af348158306bf4b66affbef to your computer and use it in GitHub Desktop.
Save RobertFischer/f165dc336af348158306bf4b66affbef to your computer and use it in GitHub Desktop.
GraphQL: Interfaces are better than Enums

Consider the following types in a schema:

type Foo {
	id:ID!
	weight:Number!
	foo:Number!
}

type Bar {
	id:ID!
	weight:Number!
	bar:String!
}

union Entity = Foo | Bar

Now, if you query this result for the ids and weights, you have to do:

entities {
	... on Foo {
		id
		weight
  	}
	... on Bar {
		id
		weight
	}
}

If, however, you have an interface, then your types look like this:

interface Entity {
	id:ID!
	weight:Number!
}

type Foo implements Entity { 
	id:ID!
	weight:Number!
	foo:Number!
}

type Bar implements Entity {
	id:ID!
	weight:Number!
	bar:String!
}

Documenting the commonalities allows clients to use the much nicer API of:

entities {
	id
	weight
}

But, even more significant than that is what happens when you introduce a new type. Let's first look at the enum case.

type Foo { 
	id:ID!
	weight:Number!
	foo:Number!
}

type Bar {
	id:ID!
	weight:Number!
	bar:String!
}

type Baz {
	id:ID!
	weight:Number!
	baz:Boolean!
}


union Entity = Foo | Bar | Baz

Now consider the client's existing query:

entities {
	... on Foo {
		id
		weight
  	}
	... on Bar {
		id
		weight
	}
}

What happens to the Baz entries? They are silently ignored. The client has silently lost access to one third of the types of data that the query returns.

On the other hand, let's look at the interface case.

interface Entity {
	id:ID!
	weight:Number!
}

type Foo implements Entity {
	id:ID!
	weight:Number!
	foo:Number!
}

type Bar implements Entity {
	id:ID!
	weight:Number!
	bar:String!
}

type Baz implements Entity {
	id:ID!
	weight:Number!
	baz:Boolean!
}

As a refresher, the existing client query looks like this:

entities {
	id
	weight
}

What happens to the Baz entities? They are returned in the results.

So an enum type should only ever be used in either of the following cases:

  1. There are literally zero fields in common, including none of the metadata fields being in common.
  2. The following are both true:
    1. The data type will never, ever be extended, and
    2. It is meaningful in the API that the client needs to specify the subtypes in order to get results (eg: filters)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment