Skip to content

TypeScript GraphQLObjectType and TArgs #2152

Closed
@williambailey

Description

@williambailey

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;
        }
        /* ... */
    },
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions