Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resolveType: remove support for returning GraphQLObjectType #2905

Merged
merged 1 commit into from Feb 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
91 changes: 6 additions & 85 deletions src/execution/__tests__/abstract-test.js
@@ -1,8 +1,6 @@
import { expect } from 'chai';
import { describe, it } from 'mocha';

import invariant from '../../jsutils/invariant';

import { parse } from '../../language/parser';

import { GraphQLSchema } from '../../type/schema';
Expand Down Expand Up @@ -297,89 +295,6 @@ describe('Execute: Handles execution of abstract types', () => {
});
});

it('deprecated(will be removed in v16.0.0): resolveType allows resolving with type object', async () => {
const PetType = new GraphQLInterfaceType({
name: 'Pet',
resolveType(obj, context) {
if (obj instanceof Dog) {
return context.async ? Promise.resolve(DogType) : DogType;
}
// istanbul ignore else (See: 'https://github.com/graphql/graphql-js/issues/2618')
if (obj instanceof Cat) {
return context.async ? Promise.resolve(CatType) : CatType;
}

// istanbul ignore next (Not reachable. All possible types have been considered)
invariant(false);
},
fields: {
name: { type: GraphQLString },
},
});

const DogType = new GraphQLObjectType({
name: 'Dog',
interfaces: [PetType],
fields: {
name: { type: GraphQLString },
woofs: { type: GraphQLBoolean },
},
});

const CatType = new GraphQLObjectType({
name: 'Cat',
interfaces: [PetType],
fields: {
name: { type: GraphQLString },
meows: { type: GraphQLBoolean },
},
});

const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
pets: {
type: new GraphQLList(PetType),
resolve() {
return [new Dog('Odie', true), new Cat('Garfield', false)];
},
},
},
}),
types: [CatType, DogType],
});

const query = `
{
pets {
name
... on Dog {
woofs
}
... on Cat {
meows
}
}
}
`;

expect(await executeQuery({ schema, query })).to.deep.equal({
data: {
pets: [
{
name: 'Odie',
woofs: true,
},
{
name: 'Garfield',
meows: false,
},
],
},
});
});

it('resolveType can throw', async () => {
const PetType = new GraphQLInterfaceType({
name: 'Pet',
Expand Down Expand Up @@ -658,5 +573,11 @@ describe('Execute: Handles execution of abstract types', () => {
expectError({ forTypeName: undefined }).toEqual(
'Abstract type "Pet" must resolve to an Object type at runtime for field "Query.pet" with value { __typename: undefined }, received "[]".',
);

// FIXME: workaround since we can't inject resolveType into SDL
(schema.getType('Pet'): any).resolveType = () => schema.getType('Cat');
expectError({ forTypeName: undefined }).toEqual(
'Support for returning GraphQLObjectType from resolveType was removed in graphql-js@16.0.0 please return type name instead.',
);
});
});
18 changes: 10 additions & 8 deletions src/execution/execute.js
Expand Up @@ -52,7 +52,6 @@ import {
GraphQLSkipDirective,
} from '../type/directives';
import {
isNamedType,
isObjectType,
isAbstractType,
isLeafType,
Expand Down Expand Up @@ -954,29 +953,32 @@ function completeAbstractValue(
}

function ensureValidRuntimeType(
runtimeTypeOrName: mixed,
runtimeTypeName: mixed,
exeContext: ExecutionContext,
returnType: GraphQLAbstractType,
fieldNodes: $ReadOnlyArray<FieldNode>,
info: GraphQLResolveInfo,
result: mixed,
): GraphQLObjectType {
if (runtimeTypeOrName == null) {
if (runtimeTypeName == null) {
throw new GraphQLError(
`Abstract type "${returnType.name}" must resolve to an Object type at runtime for field "${info.parentType.name}.${info.fieldName}". Either the "${returnType.name}" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.`,
fieldNodes,
);
}

// FIXME: temporary workaround until support for passing object types would be removed in v16.0.0
const runtimeTypeName = isNamedType(runtimeTypeOrName)
? runtimeTypeOrName.name
: runtimeTypeOrName;
// releases before 16.0.0 supported returning `GraphQLObjectType` from `resolveType`
// TODO: remove in 17.0.0 release
if (isObjectType(runtimeTypeName)) {
throw new GraphQLError(
'Support for returning GraphQLObjectType from resolveType was removed in graphql-js@16.0.0 please return type name instead.',
);
}

if (typeof runtimeTypeName !== 'string') {
throw new GraphQLError(
`Abstract type "${returnType.name}" must resolve to an Object type at runtime for field "${info.parentType.name}.${info.fieldName}" with ` +
`value ${inspect(result)}, received "${inspect(runtimeTypeOrName)}".`,
`value ${inspect(result)}, received "${inspect(runtimeTypeName)}".`,
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/type/definition.d.ts
Expand Up @@ -456,7 +456,7 @@ export type GraphQLTypeResolver<TSource, TContext> = (
context: TContext,
info: GraphQLResolveInfo,
abstractType: GraphQLAbstractType,
) => PromiseOrValue<Maybe<GraphQLObjectType<TSource, TContext> | string>>;
) => PromiseOrValue<string | undefined>;

export type GraphQLIsTypeOfFn<TSource, TContext> = (
source: TSource,
Expand Down
2 changes: 1 addition & 1 deletion src/type/definition.js
Expand Up @@ -931,7 +931,7 @@ export type GraphQLTypeResolver<TSource, TContext> = (
context: TContext,
info: GraphQLResolveInfo,
abstractType: GraphQLAbstractType,
) => PromiseOrValue<?GraphQLObjectType | string>;
) => PromiseOrValue<string | void>;

export type GraphQLIsTypeOfFn<TSource, TContext> = (
source: TSource,
Expand Down