From 10cbf4b9e63738eaa6b9673ba5164e3a0a9736e7 Mon Sep 17 00:00:00 2001 From: Emily Goodwin Date: Tue, 7 Oct 2025 22:13:46 -0400 Subject: [PATCH 1/8] add initial outline for field extensions --- spec/Appendix C -- Grammar Summary.md | 10 +++++ spec/Section 3 -- Type System.md | 58 +++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/spec/Appendix C -- Grammar Summary.md b/spec/Appendix C -- Grammar Summary.md index cc464a4a6..a7fb7ec8d 100644 --- a/spec/Appendix C -- Grammar Summary.md +++ b/spec/Appendix C -- Grammar Summary.md @@ -318,6 +318,12 @@ FieldsDefinition : { FieldDefinition+ } FieldDefinition : Description? Name ArgumentsDefinition? : Type Directives[Const]? +FieldExtension : + +- extend field MemberCoordinate ImplementsInterfaces? Directives[const]? + [lookahead != `{`] +- extend field description MemberCoordinate [lookahead != `{`] + ArgumentsDefinition : ( InputValueDefinition+ ) InputValueDefinition : Description? Name : Type DefaultValue? Directives[Const]? @@ -329,6 +335,10 @@ InterfaceTypeDefinition : - Description? interface Name ImplementsInterfaces? Directives[Const]? [lookahead != `{`] +InterfaceFieldExtension : + +- extend interface MemberCoordinate Directives[const]? + InterfaceTypeExtension : - extend interface Name ImplementsInterfaces? Directives[Const]? diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 44760852c..0b85ebce6 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -1105,6 +1105,36 @@ Object type extensions have the potential to be invalid if incorrectly defined. 6. The resulting extended object type must be a super-set of all interfaces it implements. +### Field Extensions + +FieldExtension : + +- extend field MemberCoordinate ImplementsInterfaces? Directives[const]? + [lookahead != `{`] +- extend field description MemberCoordinate [lookahead != `{`] + +Field extensions are used to represent a field which has been extended from some +previously defined field. For example this may be a GraphQL service which is +itself an extension of another GraphQL service. + +In this example, we can deprecate the id field on the User type. + +```graphql example +extend field User.name @deprecated(”Some reason”) +``` + +** Field Validation ** + +Field validation have the potential to be invalid if incorrectly defined. + +1. The field must already be defined and a field for a Type +2. Any non-repeatable directives provided must not already apply to the previous + field. +3. Any interfaces provided must not be already implemented by the previous + field. +4. The resulting extended field must be a super-set of all interfaces it + implements. + ## Interfaces InterfaceTypeDefinition : @@ -1358,6 +1388,34 @@ defined. 6. The resulting extended Interface type must be a super-set of all Interfaces it implements. +#### Interface Field Extensions + +InterfaceFieldExtension : + +- extend interface MemberCoordinate Directives[const]? + +Interface field extensions are used to represent an interface which has been +extended from some previous interface. For example this may be a GraphQL service +which is itself an extension of another GraphQL service. + +In this example, the name field on the User type is deprecated for an interface. + +```graphql example +extend interface User.name @deprecated("Some reason.") +``` + +** Field Validation ** + +Field validation have the potential to be invalid if incorrectly defined. + +1. The field must already be defined and a field for a Type +2. Any non-repeatable directives provided must not already apply to the previous + field. +3. Any interfaces provided must not be already implemented by the previous + field. +4. The resulting extended field must be a super-set of all interfaces it + implements. + ## Unions UnionTypeDefinition : Description? union Name Directives[Const]? From b14e553661921a49161114752aafe647b073be70 Mon Sep 17 00:00:00 2001 From: Emily Goodwin Date: Wed, 8 Oct 2025 22:18:00 -0400 Subject: [PATCH 2/8] address pr comments --- spec/Appendix C -- Grammar Summary.md | 11 +++----- spec/Section 3 -- Type System.md | 39 +++------------------------ 2 files changed, 6 insertions(+), 44 deletions(-) diff --git a/spec/Appendix C -- Grammar Summary.md b/spec/Appendix C -- Grammar Summary.md index a7fb7ec8d..dda675268 100644 --- a/spec/Appendix C -- Grammar Summary.md +++ b/spec/Appendix C -- Grammar Summary.md @@ -320,9 +320,8 @@ Directives[Const]? FieldExtension : -- extend field MemberCoordinate ImplementsInterfaces? Directives[const]? - [lookahead != `{`] -- extend field description MemberCoordinate [lookahead != `{`] +- extend field MemberCoordinate Directives[const]? +- extend field description MemberCoordinate ArgumentsDefinition : ( InputValueDefinition+ ) @@ -334,11 +333,7 @@ InterfaceTypeDefinition : FieldsDefinition - Description? interface Name ImplementsInterfaces? Directives[Const]? [lookahead != `{`] - -InterfaceFieldExtension : - -- extend interface MemberCoordinate Directives[const]? - + InterfaceTypeExtension : - extend interface Name ImplementsInterfaces? Directives[Const]? diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 0b85ebce6..0750d0f47 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -1109,9 +1109,8 @@ Object type extensions have the potential to be invalid if incorrectly defined. FieldExtension : -- extend field MemberCoordinate ImplementsInterfaces? Directives[const]? - [lookahead != `{`] -- extend field description MemberCoordinate [lookahead != `{`] +- extend field MemberCoordinate Directives[const]? +- extend field description MemberCoordinate Field extensions are used to represent a field which has been extended from some previously defined field. For example this may be a GraphQL service which is @@ -1127,13 +1126,9 @@ extend field User.name @deprecated(”Some reason”) Field validation have the potential to be invalid if incorrectly defined. -1. The field must already be defined and a field for a Type +1. MemberCoordinate must be resolved to an existing field on a object or interface type. 2. Any non-repeatable directives provided must not already apply to the previous field. -3. Any interfaces provided must not be already implemented by the previous - field. -4. The resulting extended field must be a super-set of all interfaces it - implements. ## Interfaces @@ -1388,34 +1383,6 @@ defined. 6. The resulting extended Interface type must be a super-set of all Interfaces it implements. -#### Interface Field Extensions - -InterfaceFieldExtension : - -- extend interface MemberCoordinate Directives[const]? - -Interface field extensions are used to represent an interface which has been -extended from some previous interface. For example this may be a GraphQL service -which is itself an extension of another GraphQL service. - -In this example, the name field on the User type is deprecated for an interface. - -```graphql example -extend interface User.name @deprecated("Some reason.") -``` - -** Field Validation ** - -Field validation have the potential to be invalid if incorrectly defined. - -1. The field must already be defined and a field for a Type -2. Any non-repeatable directives provided must not already apply to the previous - field. -3. Any interfaces provided must not be already implemented by the previous - field. -4. The resulting extended field must be a super-set of all interfaces it - implements. - ## Unions UnionTypeDefinition : Description? union Name Directives[Const]? From 20e079fc645afdbe46eb9094872038ad0dc13d90 Mon Sep 17 00:00:00 2001 From: Emily Goodwin Date: Thu, 9 Oct 2025 18:02:58 -0400 Subject: [PATCH 3/8] minor formatting changes --- spec/Appendix C -- Grammar Summary.md | 6 +++--- spec/Section 3 -- Type System.md | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/spec/Appendix C -- Grammar Summary.md b/spec/Appendix C -- Grammar Summary.md index dda675268..2d9a82a4d 100644 --- a/spec/Appendix C -- Grammar Summary.md +++ b/spec/Appendix C -- Grammar Summary.md @@ -320,8 +320,8 @@ Directives[Const]? FieldExtension : -- extend field MemberCoordinate Directives[const]? -- extend field description MemberCoordinate +- extend field MemberCoordinate Directives[Const] +- extend field Description MemberCoordinate ArgumentsDefinition : ( InputValueDefinition+ ) @@ -333,7 +333,7 @@ InterfaceTypeDefinition : FieldsDefinition - Description? interface Name ImplementsInterfaces? Directives[Const]? [lookahead != `{`] - + InterfaceTypeExtension : - extend interface Name ImplementsInterfaces? Directives[Const]? diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 0750d0f47..85d70dd24 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -1109,8 +1109,8 @@ Object type extensions have the potential to be invalid if incorrectly defined. FieldExtension : -- extend field MemberCoordinate Directives[const]? -- extend field description MemberCoordinate +- extend field MemberCoordinate Directives[Const] +- extend field Description MemberCoordinate Field extensions are used to represent a field which has been extended from some previously defined field. For example this may be a GraphQL service which is @@ -1126,7 +1126,8 @@ extend field User.name @deprecated(”Some reason”) Field validation have the potential to be invalid if incorrectly defined. -1. MemberCoordinate must be resolved to an existing field on a object or interface type. +1. MemberCoordinate must be resolved to an existing field on a object or + interface type. 2. Any non-repeatable directives provided must not already apply to the previous field. From a8deaa7cfedd0c0210b472d6f56139b851069872 Mon Sep 17 00:00:00 2001 From: egoodwinx Date: Tue, 27 Jan 2026 21:35:23 -0500 Subject: [PATCH 4/8] update to match current graphql-js implementation --- spec/Appendix C -- Grammar Summary.md | 5 --- spec/Section 3 -- Type System.md | 60 +++++++++++++++++++-------- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/spec/Appendix C -- Grammar Summary.md b/spec/Appendix C -- Grammar Summary.md index 2d9a82a4d..cc464a4a6 100644 --- a/spec/Appendix C -- Grammar Summary.md +++ b/spec/Appendix C -- Grammar Summary.md @@ -318,11 +318,6 @@ FieldsDefinition : { FieldDefinition+ } FieldDefinition : Description? Name ArgumentsDefinition? : Type Directives[Const]? -FieldExtension : - -- extend field MemberCoordinate Directives[Const] -- extend field Description MemberCoordinate - ArgumentsDefinition : ( InputValueDefinition+ ) InputValueDefinition : Description? Name : Type DefaultValue? Directives[Const]? diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 85d70dd24..8c7478e20 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -1096,40 +1096,49 @@ Object type extensions have the potential to be invalid if incorrectly defined. 1. The named type must already be defined and must be an Object type. 2. The fields of an Object type extension must have unique names; no two fields may share the same name. -3. Any fields of an Object type extension must not be already defined on the - previous Object type. -4. Any non-repeatable directives provided must not already apply to the previous +3. Any non-repeatable directives provided must not already apply to the previous Object type. -5. Any interfaces provided must not be already implemented by the previous +4. Any interfaces provided must not be already implemented by the previous Object type. -6. The resulting extended object type must be a super-set of all interfaces it +5. The resulting extended object type must be a super-set of all interfaces it implements. -### Field Extensions - -FieldExtension : - -- extend field MemberCoordinate Directives[Const] -- extend field Description MemberCoordinate +#### Field Extensions Field extensions are used to represent a field which has been extended from some previously defined field. For example this may be a GraphQL service which is -itself an extension of another GraphQL service. +itself an extension of another GraphQL service. When the same field appears in +multiple extensions, the properties are merged with later extensions taking +precedence for conflicting values. -In this example, we can deprecate the id field on the User type. +In this example, we can deprecate the field `field` on type `Query` by using a +field extension: ```graphql example -extend field User.name @deprecated(”Some reason”) +type Query { + field: String +} +``` + +```graphql example +extend type Query { + field: String @deprecated(reason: "Use newField") +} ``` ** Field Validation ** Field validation have the potential to be invalid if incorrectly defined. -1. MemberCoordinate must be resolved to an existing field on a object or - interface type. -2. Any non-repeatable directives provided must not already apply to the previous - field. +1. The field type must match the previous definition exactly +2. The argument definitions cannot change from the original definition. This + mean argument definitions cannot be added, removed, or changed. +3. The description may be added if none exists, or must match the existing + description exactly +4. The deprecation reason may be added if none exists, or must match the + existing reason exactly +5. Directives may be added but cannot conflict with existing non-repeatable + directives ## Interfaces @@ -1384,6 +1393,21 @@ defined. 6. The resulting extended Interface type must be a super-set of all Interfaces it implements. +#### Interface Field Extensions + +Interface field extensions follow the same rules as Object field extensions and +are used to extend fields on interface types. + +```graphql example +interface Node { + id: ID +} + +extend interface Node { + id: ID @deprecated(reason: "Use globalId instead") +} +``` + ## Unions UnionTypeDefinition : Description? union Name Directives[Const]? From 6cc180634d745c11a4a49c0ae54228ff79037dd3 Mon Sep 17 00:00:00 2001 From: egoodwinx Date: Wed, 28 Jan 2026 20:57:26 -0500 Subject: [PATCH 5/8] update description for default values, not all arguments --- spec/Section 3 -- Type System.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 8c7478e20..cfa3146a9 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -1131,8 +1131,7 @@ extend type Query { Field validation have the potential to be invalid if incorrectly defined. 1. The field type must match the previous definition exactly -2. The argument definitions cannot change from the original definition. This - mean argument definitions cannot be added, removed, or changed. +2. The default argument definitions may not be changed or removed. 3. The description may be added if none exists, or must match the existing description exactly 4. The deprecation reason may be added if none exists, or must match the From 28e9bbc846378e290a405d1debff4bd35a060334 Mon Sep 17 00:00:00 2001 From: egoodwinx Date: Wed, 28 Jan 2026 21:12:15 -0500 Subject: [PATCH 6/8] fix grammar --- spec/Section 3 -- Type System.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index cfa3146a9..ab96ec5d6 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -1106,10 +1106,10 @@ Object type extensions have the potential to be invalid if incorrectly defined. #### Field Extensions Field extensions are used to represent a field which has been extended from some -previously defined field. For example this may be a GraphQL service which is -itself an extension of another GraphQL service. When the same field appears in -multiple extensions, the properties are merged with later extensions taking -precedence for conflicting values. +previously defined field. For example this may be used by a GraphQL service +which is itself an extension of another GraphQL service. When the same field +appears in multiple extensions, the properties are merged with later extensions +taking precedence for conflicting values. In this example, we can deprecate the field `field` on type `Query` by using a field extension: @@ -1126,9 +1126,9 @@ extend type Query { } ``` -** Field Validation ** +** Type Validation ** -Field validation have the potential to be invalid if incorrectly defined. +Fields have the potential to be invalid if incorrectly defined. 1. The field type must match the previous definition exactly 2. The default argument definitions may not be changed or removed. From 29ef5bbcd4a012102f6dd705f0036a7ecce509b2 Mon Sep 17 00:00:00 2001 From: egoodwinx Date: Sun, 1 Feb 2026 13:10:22 -0500 Subject: [PATCH 7/8] combine field extensions into object extensions --- spec/Section 3 -- Type System.md | 57 ++++++++++++-------------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index ab96ec5d6..77515054d 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -1089,55 +1089,42 @@ In this example, a directive is added to a `User` type without adding fields: extend type User @addedDirective ``` -**Type Validation** - -Object type extensions have the potential to be invalid if incorrectly defined. - -1. The named type must already be defined and must be an Object type. -2. The fields of an Object type extension must have unique names; no two fields - may share the same name. -3. Any non-repeatable directives provided must not already apply to the previous - Object type. -4. Any interfaces provided must not be already implemented by the previous - Object type. -5. The resulting extended object type must be a super-set of all interfaces it - implements. +Object type extensions may choose to extend existing fields. -#### Field Extensions - -Field extensions are used to represent a field which has been extended from some -previously defined field. For example this may be used by a GraphQL service -which is itself an extension of another GraphQL service. When the same field -appears in multiple extensions, the properties are merged with later extensions -taking precedence for conflicting values. - -In this example, we can deprecate the field `field` on type `Query` by using a -field extension: +In this example, we can deprecate the field `id` on type `Query` by adding a +`@deprecated` directive through a type extension: ```graphql example type Query { - field: String + id: String } ``` ```graphql example extend type Query { - field: String @deprecated(reason: "Use newField") + id: String @deprecated(reason: "Use newId") } ``` -** Type Validation ** +**Type Validation** -Fields have the potential to be invalid if incorrectly defined. +Object type extensions have the potential to be invalid if incorrectly defined. -1. The field type must match the previous definition exactly -2. The default argument definitions may not be changed or removed. -3. The description may be added if none exists, or must match the existing - description exactly -4. The deprecation reason may be added if none exists, or must match the - existing reason exactly -5. Directives may be added but cannot conflict with existing non-repeatable - directives +1. The named type must already be defined and must be an Object type. +2. For each field of an Object type extension: + 1. The field must have a unique name within that Object type extension; no + two fields may share the same name. + 2. If a field with the same name exists on the previous Object type: + 1. The field type must match the previous definition exactly. + 2. The argument definitions defaultValues must match. + 3. The description or deprecation may be added if none exists, or must + match the existing description or deprecation exactly. + 4. Directives may be added but cannot conflict with existing + non-repeatable directives. +3. Any interfaces provided must not be already implemented by the previous + Object type. +4. The resulting extended object type must be a super-set of all interfaces it + implements. ## Interfaces From 2645e07aa64f80aaf4609dd2d3fe853258d62203 Mon Sep 17 00:00:00 2001 From: egoodwinx Date: Mon, 2 Feb 2026 19:55:15 -0500 Subject: [PATCH 8/8] address comments, remove interface field extensions, and add more context on extending interfaces --- spec/Section 3 -- Type System.md | 76 +++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 25 deletions(-) diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 77515054d..472bb332f 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -1089,10 +1089,10 @@ In this example, a directive is added to a `User` type without adding fields: extend type User @addedDirective ``` -Object type extensions may choose to extend existing fields. +Object type extensions may extend existing fields. -In this example, we can deprecate the field `id` on type `Query` by adding a -`@deprecated` directive through a type extension: +In this example, we deprecate the field `id` on type `Query` by adding a +`@deprecated` directive: ```graphql example type Query { @@ -1116,11 +1116,19 @@ Object type extensions have the potential to be invalid if incorrectly defined. two fields may share the same name. 2. If a field with the same name exists on the previous Object type: 1. The field type must match the previous definition exactly. - 2. The argument definitions defaultValues must match. - 3. The description or deprecation may be added if none exists, or must - match the existing description or deprecation exactly. - 4. Directives may be added but cannot conflict with existing - non-repeatable directives. + 2. The field description must match the previous definition exactly. + 3. Any non-repeatable directives provided must not already apply to the + previous definition. + 4. For each argument of the field: + 1. If an argument with the same name exists on the previous field + definition: + 1. The argument type must match the previous definition exactly. + 2. If the argument has a default value, it must match the previous + definition exactly. + 3. The argument description must match the previous definition + exactly. + 4. Any non-repeatable directives provided must not already apply to + the previous definition. 3. Any interfaces provided must not be already implemented by the previous Object type. 4. The resulting extended object type must be a super-set of all interfaces it @@ -1361,14 +1369,47 @@ fields: extend interface NamedEntity @addedDirective ``` +Interface type extensions may extend existing fields. + +In this example, we deprecate the field `id` on type `Query` by adding a +`@deprecated` directive: + +```graphql example +interface Node { + id: ID +} +``` + +```graphql example +extend interface Node { + id: ID @deprecated(reason: "Use globalId instead") +} +``` + **Type Validation** Interface type extensions have the potential to be invalid if incorrectly defined. 1. The named type must already be defined and must be an Interface type. -2. The fields of an Interface type extension must have unique names; no two - fields may share the same name. +2. For each field of an Interface type extension: + 1. The field must have a unique name within that Interface type extension; no + two fields may share the same name. + 2. If a field with the same name exists on the previous Interface type: + 1. The field type must match the previous definition exactly. + 2. The field description must match the previous definition exactly. + 3. Any non-repeatable directives provided must not already apply to the + previous definition. + 4. For each argument of the field: + 1. If an argument with the same name exists on the previous field + definition: + 1. The argument type must match the previous definition exactly. + 2. If the argument has a default value, it must match the previous + definition exactly. + 3. The argument description must match the previous definition + exactly. + 4. Any non-repeatable directives provided must not already apply to + the previous definition. 3. Any fields of an Interface type extension must not be already defined on the previous Interface type. 4. Any Object or Interface type which implemented the previous Interface type @@ -1379,21 +1420,6 @@ defined. 6. The resulting extended Interface type must be a super-set of all Interfaces it implements. -#### Interface Field Extensions - -Interface field extensions follow the same rules as Object field extensions and -are used to extend fields on interface types. - -```graphql example -interface Node { - id: ID -} - -extend interface Node { - id: ID @deprecated(reason: "Use globalId instead") -} -``` - ## Unions UnionTypeDefinition : Description? union Name Directives[Const]?