@@ -654,14 +654,19 @@ func completeAbstractValue(eCtx *ExecutionContext, returnType Abstract, fieldAST
654
654
655
655
var runtimeType * Object
656
656
657
- if returnType , ok := returnType .(Abstract ); ok {
658
- runtimeType = returnType .ObjectType (result , info )
659
- if runtimeType != nil && ! returnType .IsPossibleType (runtimeType ) {
660
- panic (gqlerrors .NewFormattedError (
661
- fmt .Sprintf (`Runtime Object type "%v" is not a possible type ` +
662
- `for "%v".` , runtimeType , returnType ),
663
- ))
664
- }
657
+ if unionReturnType , ok := returnType .(* Union ); ok && unionReturnType .ResolveType != nil {
658
+ runtimeType = unionReturnType .ResolveType (result , info )
659
+ } else if interfaceReturnType , ok := returnType .(* Interface ); ok && interfaceReturnType .ResolveType != nil {
660
+ runtimeType = interfaceReturnType .ResolveType (result , info )
661
+ } else {
662
+ runtimeType = defaultResolveTypeFn (result , info , returnType )
663
+ }
664
+
665
+ if runtimeType != nil && ! returnType .IsPossibleType (runtimeType ) {
666
+ panic (gqlerrors .NewFormattedError (
667
+ fmt .Sprintf (`Runtime Object type "%v" is not a possible type ` +
668
+ `for "%v".` , runtimeType , returnType ),
669
+ ))
665
670
}
666
671
667
672
if runtimeType == nil {
@@ -749,6 +754,26 @@ func completeListValue(eCtx *ExecutionContext, returnType *List, fieldASTs []*as
749
754
return completedResults
750
755
}
751
756
757
+ // defaultResolveTypeFn If a resolveType function is not given, then a default resolve behavior is
758
+ // used which tests each possible type for the abstract type by calling
759
+ // isTypeOf for the object being coerced, returning the first type that matches.
760
+ func defaultResolveTypeFn (value interface {}, info ResolveInfo , abstractType Abstract ) * Object {
761
+ possibleTypes := abstractType .PossibleTypes ()
762
+ for _ , possibleType := range possibleTypes {
763
+ if possibleType .IsTypeOf == nil {
764
+ continue
765
+ }
766
+ if res := possibleType .IsTypeOf (value , info ); res {
767
+ return possibleType
768
+ }
769
+ }
770
+ return nil
771
+ }
772
+
773
+ // defaultResolveFn If a resolve function is not given, then a default resolve behavior is used
774
+ // which takes the property of the source object of the same name as the field
775
+ // and returns it as the result, or if it's a function, returns the result
776
+ // of calling that function.
752
777
func defaultResolveFn (p ResolveParams ) (interface {}, error ) {
753
778
// try to resolve p.Source as a struct first
754
779
sourceVal := reflect .ValueOf (p .Source )
0 commit comments