Definitelytyped: Using strictFunctionTypes option throws when typing GraphQL resolvers

Created on 9 Nov 2017  路  14Comments  路  Source: DefinitelyTyped/DefinitelyTyped

  • [x] I tried using the @types/graphql package and had problems.
  • [x] I tried using the latest stable version of tsc. https://www.npmjs.com/package/typescript
  • [x] I have a question that is inappropriate for StackOverflow. (Please ask any appropriate questions there).
  • [x] [Mention](https://github.com/blog/821-mention-somebody-they-re-notified) the authors (see Definitions by: in index.d.ts) so they can respond.

    • Authors: @TonyPythoneer, @calebmer, @intellix, @firede, @kepennar, @freiksenet, @IvanGoncharov, @DxCx

I have a very simple resolver function that is throwing an error and I think I've narrowed it down to being related to the new strictFunctionTypes flag introduced with TS 2.6. If I set that flag to false I don't see the error. If I include a single resolver argument or if I specify the second parameter to match the GraphQLFieldResolver signature (args: { [argName: string]: any }) it compiles. I'm still trying to wrap my head around the whole contravariance topic and I'm unclear at this point what would be needed to modify the TS definitions. I'd really like to continue using strict: true, but I'm failing to see how resolvers can be appropriately typed.

const resolverMap = {
  Query: {
    getTagById(source: undefined, args: { id: number }) {
      // ...
    },
  }
}
error TS2345: Argument of type '{ typeDefs: string; resolvers: { Query: { getTagById(source:
undefined, args: { id: number; }): B...' is not assignable to parameter of type 'IExecutableSchemaDefinition'.
  Types of property 'resolvers' are incompatible.
    Type '{ Query: { getTagById(source: undefined, args: { id: number; }): Bluebird<{} | null>; getTags(): ...'
 is not assignable to type 'IResolvers | undefined'.
      Type '{ Query: { getTagById(source: undefined, args: { id: number; }): Bluebird<{} | null>; getTags(): ..
.' is not assignable to type 'IResolvers'.
        Property 'Query' is incompatible with index signature.
          Type '{ getTagById(source: undefined, args: { id: number; }): Bluebird<{} | null>; getTags(): Bluebir
d<...' is not assignable to type 'GraphQLScalarType | IResolverObject | (() => any)'.
            Type '{ getTagById(source: undefined, args: { id: number; }): Bluebird<{} | null>; getTags(): Blueb
ird<...' is not assignable to type '() => any'.
              Type '{ getTagById(source: undefined, args: { id: number; }): Bluebird<{} | null>; getTags(): Blu
ebird<...' provides no match for the signature '(): any'.

Most helpful comment

I'm not convinced this issue has been resolved. As I mentioned in #22789, I still can't include args in a resolver function without a TS error. I'd be interested to know if anyone is successfully compiling their GraphQL project using TS in strict mode. From every attempt I've made, it doesn't seem possible without turning off strictFunctionTypes.

All 14 comments

I modified the GraphQLFieldResolver definition like the following and the project compiled successfully with "strictFunctionTypes": true. I'm hoping someone can review this to determine whether this makes sense or can suggest a better/proper solution.

export type GraphQLFieldResolver<TSource, TContext, TArgs = any> = (
  source: TSource,
  args: TArgs & { [argName: string]: any },
  context: TContext,
  info: GraphQLResolveInfo,
) => any;

I didn't try the proposed solution but I confirm the issue with strictFunctionTypes: true and Typescript 2.6

LGTM 馃憤

@corydeppen: We encountered the same issue and implemented this solution and everything is fine so far, it would be great if someone could make a PR :)

Fixed by #22789

I'm not convinced this issue has been resolved. As I mentioned in #22789, I still can't include args in a resolver function without a TS error. I'd be interested to know if anyone is successfully compiling their GraphQL project using TS in strict mode. From every attempt I've made, it doesn't seem possible without turning off strictFunctionTypes.

Seeing this issue too. If I have a resolver with a typed args (e.g. I'm using something more specific than just { [arg: string]: any } as the type for the args parameter) I'm getting TS errors.

I'm living with it by casting:

makeExecutableSchema({
  /* ... */
  resolvers: {
    Mutation: {
      doSomething: doSomething as () => any
    }
  }
});

It's pretty unpleasant though.

I'm having this issue as well. My project compiles if I assign args to an empty object but when adding any typed properties I can't compile

I'm experiencing the same issue while using graphql-yoga
https://github.com/prismagraphql/graphql-yoga/issues/379

I'm having similar issue with IResolver. My project compiles if I modify it but appending | any at Interface.d.ts definition:

export interface IResolvers<TSource = any, TContext = any> {
[key: string]: (() => any) | IResolverObject<TSource, TContext> | GraphQLScalarType | IEnumResolver | any;
}

I'm breaking the type checking facility like other cited or workaround solutions.

Can confirm this is still a problem. Any followup on this? Setting type to any fixes compilation, but typing properties fails.

@steven-isbell I don't think there are any news on this other than the stuff in this issue (and the related issues linked above). At the moment what I do to get better intellisense on VSCode is to set the type to be MyType | any but that still leaves you exposed to the any type uncertainties, which is not great.

@steven-isbell Has there been any update on this? Any idea on how to fix this without changing the interface.ts or definition.d.ts would be great.

Am no longer using @types/graphql and just use the officially bundled ones with the graphql-js repository.

Was this page helpful?
0 / 5 - 0 ratings