@@ -66,6 +66,15 @@ export type GraphQLType =
6666 | GraphQLEnumType
6767 | GraphQLInputObjectType
6868 | GraphQLList < GraphQLType >
69+ >
70+ | GraphQLSemanticNonNull <
71+ | GraphQLScalarType
72+ | GraphQLObjectType
73+ | GraphQLInterfaceType
74+ | GraphQLUnionType
75+ | GraphQLEnumType
76+ | GraphQLInputObjectType
77+ | GraphQLList < GraphQLType >
6978 > ;
7079
7180export function isType ( type : unknown ) : type is GraphQLType {
@@ -77,7 +86,8 @@ export function isType(type: unknown): type is GraphQLType {
7786 isEnumType ( type ) ||
7887 isInputObjectType ( type ) ||
7988 isListType ( type ) ||
80- isNonNullType ( type )
89+ isNonNullType ( type ) ||
90+ isSemanticNonNullType ( type )
8191 ) ;
8292}
8393
@@ -203,6 +213,32 @@ export function assertNonNullType(type: unknown): GraphQLNonNull<GraphQLType> {
203213 return type ;
204214}
205215
216+ export function isSemanticNonNullType (
217+ type : GraphQLInputType ,
218+ ) : type is GraphQLSemanticNonNull < GraphQLInputType > ;
219+ export function isSemanticNonNullType (
220+ type : GraphQLOutputType ,
221+ ) : type is GraphQLSemanticNonNull < GraphQLOutputType > ;
222+ export function isSemanticNonNullType (
223+ type : unknown ,
224+ ) : type is GraphQLSemanticNonNull < GraphQLType > ;
225+ export function isSemanticNonNullType (
226+ type : unknown ,
227+ ) : type is GraphQLSemanticNonNull < GraphQLType > {
228+ return instanceOf ( type , GraphQLSemanticNonNull ) ;
229+ }
230+
231+ export function assertSemanticNonNullType (
232+ type : unknown ,
233+ ) : GraphQLSemanticNonNull < GraphQLType > {
234+ if ( ! isSemanticNonNullType ( type ) ) {
235+ throw new Error (
236+ `Expected ${ inspect ( type ) } to be a GraphQL Semantic-Non-Null type.` ,
237+ ) ;
238+ }
239+ return type ;
240+ }
241+
206242/**
207243 * These types may be used as input types for arguments and directives.
208244 */
@@ -217,6 +253,7 @@ export type GraphQLInputType =
217253 | GraphQLInputObjectType
218254 | GraphQLList < GraphQLInputType >
219255 > ;
256+ // Note: GraphQLSemanticNonNull is currently not allowed for input types
220257
221258export function isInputType ( type : unknown ) : type is GraphQLInputType {
222259 return (
@@ -251,6 +288,14 @@ export type GraphQLOutputType =
251288 | GraphQLUnionType
252289 | GraphQLEnumType
253290 | GraphQLList < GraphQLOutputType >
291+ >
292+ | GraphQLSemanticNonNull <
293+ | GraphQLScalarType
294+ | GraphQLObjectType
295+ | GraphQLInterfaceType
296+ | GraphQLUnionType
297+ | GraphQLEnumType
298+ | GraphQLList < GraphQLOutputType >
254299 > ;
255300
256301export function isOutputType ( type : unknown ) : type is GraphQLOutputType {
@@ -414,16 +459,66 @@ export class GraphQLNonNull<T extends GraphQLNullableType> {
414459 }
415460}
416461
462+ /**
463+ * Semantic-Non-Null Type Wrapper
464+ *
465+ * A semantic-non-null is a wrapping type which points to another type.
466+ * Semantic-non-null types enforce that their values are never null unless
467+ * caused by an error being raised. It is useful for fields which you can make
468+ * a guarantee on non-nullability in a no-error case, for example when you know
469+ * that a related entity must exist (but acknowledge that retrieving it may
470+ * produce an error).
471+ *
472+ * Example:
473+ *
474+ * ```ts
475+ * const RowType = new GraphQLObjectType({
476+ * name: 'Row',
477+ * fields: () => ({
478+ * email: { type: new GraphQLSemanticNonNull(GraphQLString) },
479+ * })
480+ * })
481+ * ```
482+ * Note: the enforcement of non-nullability occurs within the executor.
483+ *
484+ * @experimental
485+ */
486+ export class GraphQLSemanticNonNull < T extends GraphQLNullableType > {
487+ readonly ofType : T ;
488+
489+ constructor ( ofType : T ) {
490+ devAssert (
491+ isNullableType ( ofType ) ,
492+ `Expected ${ inspect ( ofType ) } to be a GraphQL nullable type.` ,
493+ ) ;
494+
495+ this . ofType = ofType ;
496+ }
497+
498+ get [ Symbol . toStringTag ] ( ) {
499+ return 'GraphQLSemanticNonNull' ;
500+ }
501+
502+ toString ( ) : string {
503+ return String ( this . ofType ) + '*' ;
504+ }
505+
506+ toJSON ( ) : string {
507+ return this . toString ( ) ;
508+ }
509+ }
510+
417511/**
418512 * These types wrap and modify other types
419513 */
420514
421515export type GraphQLWrappingType =
422516 | GraphQLList < GraphQLType >
423- | GraphQLNonNull < GraphQLType > ;
517+ | GraphQLNonNull < GraphQLType >
518+ | GraphQLSemanticNonNull < GraphQLType > ;
424519
425520export function isWrappingType ( type : unknown ) : type is GraphQLWrappingType {
426- return isListType ( type ) || isNonNullType ( type ) ;
521+ return isListType ( type ) || isNonNullType ( type ) || isSemanticNonNullType ( type ) ;
427522}
428523
429524export function assertWrappingType ( type : unknown ) : GraphQLWrappingType {
@@ -446,7 +541,7 @@ export type GraphQLNullableType =
446541 | GraphQLList < GraphQLType > ;
447542
448543export function isNullableType ( type : unknown ) : type is GraphQLNullableType {
449- return isType ( type ) && ! isNonNullType ( type ) ;
544+ return isType ( type ) && ! isNonNullType ( type ) && ! isSemanticNonNullType ( type ) ;
450545}
451546
452547export function assertNullableType ( type : unknown ) : GraphQLNullableType {
@@ -458,7 +553,7 @@ export function assertNullableType(type: unknown): GraphQLNullableType {
458553
459554export function getNullableType ( type : undefined | null ) : void ;
460555export function getNullableType < T extends GraphQLNullableType > (
461- type : T | GraphQLNonNull < T > ,
556+ type : T | GraphQLNonNull < T > | GraphQLSemanticNonNull < T > ,
462557) : T ;
463558export function getNullableType (
464559 type : Maybe < GraphQLType > ,
@@ -467,12 +562,14 @@ export function getNullableType(
467562 type : Maybe < GraphQLType > ,
468563) : GraphQLNullableType | undefined {
469564 if ( type ) {
470- return isNonNullType ( type ) ? type . ofType : type ;
565+ return isNonNullType ( type ) || isSemanticNonNullType ( type )
566+ ? type . ofType
567+ : type ;
471568 }
472569}
473570
474571/**
475- * These named types do not include modifiers like List or NonNull.
572+ * These named types do not include modifiers like List, NonNull, or SemanticNonNull
476573 */
477574export type GraphQLNamedType = GraphQLNamedInputType | GraphQLNamedOutputType ;
478575
0 commit comments