@@ -1092,7 +1092,9 @@ function ensureValidRuntimeType(
1092
1092
throw new GraphQLError (
1093
1093
`Abstract type ${ returnType . name } must resolve to an Object type at ` +
1094
1094
`runtime for field ${ info . parentType . name } .${ info . fieldName } with ` +
1095
- `value "${ String ( result ) } ", received "${ String ( runtimeType ) } ".` ,
1095
+ `value "${ String ( result ) } ", received "${ String ( runtimeType ) } ". ` +
1096
+ `Either the ${ returnType . name } type should provide a "resolveType" ` +
1097
+ 'function or each possible types should provide an "isTypeOf" function.' ,
1096
1098
fieldNodes
1097
1099
) ;
1098
1100
}
@@ -1197,15 +1199,30 @@ function collectAndExecuteSubfields(
1197
1199
1198
1200
/**
1199
1201
* If a resolveType function is not given, then a default resolve behavior is
1200
- * used which tests each possible type for the abstract type by calling
1202
+ * used which attempts two strategies:
1203
+ *
1204
+ * First, See if the provided value has a `__typename` field defined, if so, use
1205
+ * that value as name of the resolved type.
1206
+ *
1207
+ * Otherwise, test each possible type for the abstract type by calling
1201
1208
* isTypeOf for the object being coerced, returning the first type that matches.
1202
1209
*/
1203
1210
function defaultResolveTypeFn (
1204
1211
value : mixed ,
1205
1212
context : mixed ,
1206
1213
info : GraphQLResolveInfo ,
1207
1214
abstractType : GraphQLAbstractType
1208
- ) : ?GraphQLObjectType | Promise < ?GraphQLObjectType > {
1215
+ ) : ?GraphQLObjectType | string | Promise < ?GraphQLObjectType | string > {
1216
+ // First, look for `__typename`.
1217
+ if (
1218
+ value !== null &&
1219
+ typeof value === 'object' &&
1220
+ typeof value . __typename === 'string'
1221
+ ) {
1222
+ return value . __typename ;
1223
+ }
1224
+
1225
+ // Otherwise, test each possible type.
1209
1226
const possibleTypes = info . schema . getPossibleTypes ( abstractType ) ;
1210
1227
const promisedIsTypeOfResults = [ ] ;
1211
1228
0 commit comments