@@ -66,6 +66,15 @@ export type GraphQLType =
66
66
| GraphQLEnumType
67
67
| GraphQLInputObjectType
68
68
| GraphQLList < GraphQLType >
69
+ >
70
+ | GraphQLSemanticNonNull <
71
+ | GraphQLScalarType
72
+ | GraphQLObjectType
73
+ | GraphQLInterfaceType
74
+ | GraphQLUnionType
75
+ | GraphQLEnumType
76
+ | GraphQLInputObjectType
77
+ | GraphQLList < GraphQLType >
69
78
> ;
70
79
71
80
export function isType ( type : unknown ) : type is GraphQLType {
@@ -77,7 +86,8 @@ export function isType(type: unknown): type is GraphQLType {
77
86
isEnumType ( type ) ||
78
87
isInputObjectType ( type ) ||
79
88
isListType ( type ) ||
80
- isNonNullType ( type )
89
+ isNonNullType ( type ) ||
90
+ isSemanticNonNullType ( type )
81
91
) ;
82
92
}
83
93
@@ -203,6 +213,32 @@ export function assertNonNullType(type: unknown): GraphQLNonNull<GraphQLType> {
203
213
return type ;
204
214
}
205
215
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
+
206
242
/**
207
243
* These types may be used as input types for arguments and directives.
208
244
*/
@@ -217,6 +253,7 @@ export type GraphQLInputType =
217
253
| GraphQLInputObjectType
218
254
| GraphQLList < GraphQLInputType >
219
255
> ;
256
+ // Note: GraphQLSemanticNonNull is currently not allowed for input types
220
257
221
258
export function isInputType ( type : unknown ) : type is GraphQLInputType {
222
259
return (
@@ -251,6 +288,14 @@ export type GraphQLOutputType =
251
288
| GraphQLUnionType
252
289
| GraphQLEnumType
253
290
| GraphQLList < GraphQLOutputType >
291
+ >
292
+ | GraphQLSemanticNonNull <
293
+ | GraphQLScalarType
294
+ | GraphQLObjectType
295
+ | GraphQLInterfaceType
296
+ | GraphQLUnionType
297
+ | GraphQLEnumType
298
+ | GraphQLList < GraphQLOutputType >
254
299
> ;
255
300
256
301
export function isOutputType ( type : unknown ) : type is GraphQLOutputType {
@@ -414,16 +459,66 @@ export class GraphQLNonNull<T extends GraphQLNullableType> {
414
459
}
415
460
}
416
461
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
+
417
511
/**
418
512
* These types wrap and modify other types
419
513
*/
420
514
421
515
export type GraphQLWrappingType =
422
516
| GraphQLList < GraphQLType >
423
- | GraphQLNonNull < GraphQLType > ;
517
+ | GraphQLNonNull < GraphQLType >
518
+ | GraphQLSemanticNonNull < GraphQLType > ;
424
519
425
520
export function isWrappingType ( type : unknown ) : type is GraphQLWrappingType {
426
- return isListType ( type ) || isNonNullType ( type ) ;
521
+ return isListType ( type ) || isNonNullType ( type ) || isSemanticNonNullType ( type ) ;
427
522
}
428
523
429
524
export function assertWrappingType ( type : unknown ) : GraphQLWrappingType {
@@ -446,7 +541,7 @@ export type GraphQLNullableType =
446
541
| GraphQLList < GraphQLType > ;
447
542
448
543
export function isNullableType ( type : unknown ) : type is GraphQLNullableType {
449
- return isType ( type ) && ! isNonNullType ( type ) ;
544
+ return isType ( type ) && ! isNonNullType ( type ) && ! isSemanticNonNullType ( type ) ;
450
545
}
451
546
452
547
export function assertNullableType ( type : unknown ) : GraphQLNullableType {
@@ -458,7 +553,7 @@ export function assertNullableType(type: unknown): GraphQLNullableType {
458
553
459
554
export function getNullableType ( type : undefined | null ) : void ;
460
555
export function getNullableType < T extends GraphQLNullableType > (
461
- type : T | GraphQLNonNull < T > ,
556
+ type : T | GraphQLNonNull < T > | GraphQLSemanticNonNull < T > ,
462
557
) : T ;
463
558
export function getNullableType (
464
559
type : Maybe < GraphQLType > ,
@@ -467,12 +562,14 @@ export function getNullableType(
467
562
type : Maybe < GraphQLType > ,
468
563
) : GraphQLNullableType | undefined {
469
564
if ( type ) {
470
- return isNonNullType ( type ) ? type . ofType : type ;
565
+ return isNonNullType ( type ) || isSemanticNonNullType ( type )
566
+ ? type . ofType
567
+ : type ;
471
568
}
472
569
}
473
570
474
571
/**
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
476
573
*/
477
574
export type GraphQLNamedType = GraphQLNamedInputType | GraphQLNamedOutputType ;
478
575
0 commit comments