diff --git a/src/type/__tests__/validation-test.ts b/src/type/__tests__/validation-test.ts index 9e003d874e..c1ed85d7b6 100644 --- a/src/type/__tests__/validation-test.ts +++ b/src/type/__tests__/validation-test.ts @@ -3353,6 +3353,33 @@ describe('Interfaces must adhere to Interface they implement', () => { }, ]); }); + + it('rejects deprecated implementation field when interface field is not deprecated', () => { + const schema = buildSchema(` + interface Node { + id: ID! + } + + type Foo implements Node { + id: ID! @deprecated + } + + type Query { + foo: Foo + } + `); + + expectJSON(validateSchema(schema)).toDeepEqual([ + { + message: + 'Interface field Node.id is not deprecated, so implementation field Foo.id must not be deprecated.', + locations: [ + { line: 7, column: 17 }, + { line: 7, column: 13 }, + ], + }, + ]); + }); }); describe('assertValidSchema', () => { diff --git a/src/type/validate.ts b/src/type/validate.ts index 88e2dbb992..0a8193d501 100644 --- a/src/type/validate.ts +++ b/src/type/validate.ts @@ -573,6 +573,21 @@ function validateTypeImplementsInterface( } } } + + // Asserts that field is not deprecated unless interface field is + if ( + typeField.deprecationReason != null && + ifaceField.deprecationReason == null + ) { + context.reportError( + `Interface field ${iface.name}.${ifaceField.name} is not deprecated, so ` + + `implementation field ${type.name}.${typeField.name} must not be deprecated.`, + [ + getDeprecatedDirectiveNode(typeField.astNode), + typeField.astNode?.type, + ], + ); + } } }