Description
The TypeScript definitions currently specify a TArgs
generic type on GraphQLObjectType
which then flows into GraphQLObjectTypeConfig
, GraphQLFieldConfigMap
and GraphQLFieldMap
.
All field resolver arguments on an object therefore have to have the same base type.
This, to me, is unexpected as each resolve function can have it's own differing requirements as to what arguments and it makes it awkward to use types arguments as you need to specify something like any
when creating the GraphQLObjectType
instance. For example:
interface MySource { /* ... */ }
interface MyContext { /* ... */ }
interface MyFieldArgs {
foo?: number;
bar: string;
}
interface MyOtherFieldArgs {
baz: string;
}
const MyType = new GraphQLObjectType<MySource, MyContext, any>({
fields: {
myField: {
args: {
bar: { type: new GraphQLNonNull(GraphQLString) },
foo: { type: GraphQLInt },
},
resolve: (source, args: MyFieldArgs, context, info) => { /* ... */ },
type: GraphQLString,
},
myOtherField: {
args: {
baz: { type: GraphQLString },
},
resolve: (source, args: MyOtherFieldArgs, context, info) => { /* ... */ },
type: GraphQLString,
},
},
name: "My",
});
I suppose you could stick with the default TArgs
type and then use a typescript user-defined type guard. However this is even more awkward and seems unnecessary given that we are specifying the arguments in the GraphQLFieldConfig
and can be sure that graphql has already validated and asserted that the arguments match what we expect when it comes to calling the resolve function.
function isMyFieldArgs(o: any): o is MyFieldArgs {
/* check everything ... */
return true;
}
{
// ...
resolve: (source, args, context, info) => {
if (!isMyFieldArgs(args)) {
return undefined;
}
/* ... */
},
}