Graphql-code-generator: [Typescript-Resolvers] Custom scalar resolvers should not be optional

Created on 25 Nov 2019  路  4Comments  路  Source: dotansimha/graphql-code-generator

When generating resolvers for a schema with custom scalar types, it creates the custom scalar resolver for the type as an optional field. But the typing of graphql-tools's makeExecutableSchema function only accepts it if it's non-optional.

This seems similar to, or related to, #2780, though not exactly the same. As with that one, typescript is complaining that an optional field doesn't match an index signature that doesn't allow undefined.

A reduced reproduction of this based, on the codesandbox issue template, is at:

https://codesandbox.io/s/graphql-codegen-issue-scalartypes-nullable-3ehsu

I've left the sandbox in a state with a workaround that allows it to compile; take a look at the line in server.ts:

const resolvers: Resolvers & { DateTime: GraphQLScalarType } = {

This should just be const resolvers: Resolvers = { but that causes a type error when you try to pass that as resolvers to makeExecutableSchema. In this example, if you do that, the type error for a custom scalar type called DateTime looks like this:

server.ts:36:7 - error TS2322: Type 'Resolvers<any>' is not assignable to type 'IResolvers<any, any> | IResolvers<any, any>[] | undefined'.
  Type 'Resolvers<any>' is not assignable to type 'IResolvers<any, any>'.
    Property 'DateTime' is incompatible with index signature.
      Type 'GraphQLScalarType | undefined' is not assignable to type 'GraphQLScalarType | (()=> any) | IEnumResolver | IResolverObject<any,any, any> | IResolverOptions<any, any, any>'.
        Type 'undefined' is not assignable to type 'GraphQLScalarType | (() => any) | IEnumResolver | IResolverObject<any, any, any> | IResolverOptions<any, any, any>'.

36       resolvers
         ~~~~~~~~~

  node_modules/graphql-tools/dist/Interfaces.d.ts:86:5
    86     resolvers?: IResolvers<any, TContext> | Array<IResolvers<any, TContext>>;
           ~~~~~~~~~
    The expected type comes from property 'resolvers' which is declared here on type 'IExecutableSchemaDefinition<any>'
  1. My GraphQL schema:

Schema from the sandbox:

type Query {
    user(id: ID!): User!
}

type User {
    id: ID!
    username: String!
    email: String!
    created: DateTime
}

scalar DateTime

The custom scalar what triggers the issue.

  1. My GraphQL operations:

None - this is about resolvers for the schema, not operations.

  1. My codegen.yml config file:

From the sandbox:

schema: schema.graphql
generates:
  types.ts:
    plugins:
      - typescript
      - typescript-resolvers

Expected behavior
A variable of the generated type Resolvers should be passable to makeExecutableSchema from graphql-tools, without having to add extra type annotations to it.

Environment:

  • OS: Linux / Mac OS
  • @graphql-codegen/...: 1.8.3
  • NodeJS: 10.16.0
plugins waiting-for-answer

Most helpful comment

Yes, useIndexSignature: true does get rid of the type error. Kind of a shame it has to be used, but it does work. In the case where there's only one or two custom scalars one might prefer the workaround of adding a non-optional signature for only those, to keep typescript enforcing correctness of the resolver names, but with a lot of them that'd get really awkward fast.

All 4 comments

@kamilkisiela can you please take a look?

useIndexSignature: true should be used, right ? @dotansimha

Yes, useIndexSignature: true does get rid of the type error. Kind of a shame it has to be used, but it does work. In the case where there's only one or two custom scalars one might prefer the workaround of adding a non-optional signature for only those, to keep typescript enforcing correctness of the resolver names, but with a lot of them that'd get really awkward fast.

@MicahChalmer do you think there is a better solution? or something we can improve in the generated code?

Was this page helpful?
0 / 5 - 0 ratings