diff --git a/src/type/__tests__/validation-test.js b/src/type/__tests__/validation-test.js index c1d328582a..c04905b3c9 100644 --- a/src/type/__tests__/validation-test.js +++ b/src/type/__tests__/validation-test.js @@ -1205,7 +1205,7 @@ describe('Type System: Interface fields must have output types', () => { ]); }); - it('accepts an interface not implemented by at least one object', () => { + it('rejects an interface not implemented by at least one object', () => { const schema = buildSchema(` type Query { test: SomeInterface @@ -1215,7 +1215,13 @@ describe('Type System: Interface fields must have output types', () => { foo: String } `); - expect(validateSchema(schema)).to.deep.equal([]); + expect(validateSchema(schema)).to.deep.equal([ + { + message: + 'Interface SomeInterface must be implemented by at least one Object type.', + locations: [{ line: 6, column: 7 }], + }, + ]); }); }); diff --git a/src/type/validate.js b/src/type/validate.js index b02134775f..a5cc5591f8 100644 --- a/src/type/validate.js +++ b/src/type/validate.js @@ -257,6 +257,9 @@ function validateTypes(context: SchemaValidationContext): void { } else if (isInterfaceType(type)) { // Ensure fields are valid. validateFields(context, type); + + // Ensure Interfaces include at least 1 Object type. + validateInterfaces(context, type); } else if (isUnionType(type)) { // Ensure Unions include valid member types. validateUnionMembers(context, type); @@ -364,6 +367,21 @@ function validateObjectInterfaces( }); } +function validateInterfaces( + context: SchemaValidationContext, + iface: GraphQLInterfaceType, +): void { + const possibleTypes = context.schema.getPossibleTypes(iface); + + if (possibleTypes.length === 0) { + context.reportError( + `Interface ${iface.name} must be implemented ` + + `by at least one Object type.`, + iface.astNode, + ); + } +} + function validateObjectImplementsInterface( context: SchemaValidationContext, object: GraphQLObjectType,