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>'
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.
None - this is about resolvers for the schema, not operations.
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:
@graphql-codegen/...: 1.8.3@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?
Most helpful comment
Yes,
useIndexSignature: truedoes 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.