Search code examples
typescriptgraphqlcode-generation

TypeScript Types conflict with graphql types


I have a GraphQL resolver and schema that look like this:

import { Resolvers } from "../../generated/schema";

export const resolvers: Resolvers = {
  Query: {
    getS: async (_parent: unknown, { id }: { id: string }): Promise<GenericResponse<S>> => { ... }
    }
}

and

type Query {
  getS(id: ID!): getSResponse
}

type S {
  id: ID!,
  wac: Float!,
  beginDate: String!,
  endDate: String!,
}

type getSResponse implements GenericResponse {
  status: Status!
  data: S!
}

I'm using GraphQL codegen to check types for resolver functions with the following contents:

export type Resolvers<ContextType = any> = {
  Query?: QueryResolvers<ContextType>;
}

export type QueryResolvers<ContextType = any, ParentType extends ResolversParentTypes['Query'] = ResolversParentTypes['Query']> = {
getS?: Resolver<Maybe<ResolversTypes['getSResponse']>, ParentType, ContextType, RequireFields<QueryGetSArgs, 'id'>>;
}

export type QueryGetSArgs = {
  id: Scalars['ID']['input'];
};

export type Scalars = {
  ID: { input: string | number; output: string; }
  String: { input: string; output: string; }
  Boolean: { input: boolean; output: boolean; }
  Int: { input: number; output: number; }
  Float: { input: number; output: number; }
};

However, I am getting this typescript error:

Type '(_parent: unknown, { id }: myType) => Promise<GenericResponse<S>>' is not assignable to type 'Resolver<Maybe<ResolverTypeWrapper<GetWacPercentageResponse>>, {}, any, RequireFields<QueryGetSArgs, "id">> | undefined'.
  Type '(_parent: unknown, { id }: myType) => Promise<GenericResponse<S>>' is not assignable to type 'ResolverFn<Maybe<ResolverTypeWrapper<GetSResponse>>, {}, any, RequireFields<QueryGetSArgs, "id">>'.
    Types of parameters '__1' and 'args' are incompatible.
      Type 'RequireFields<QueryGetSArgs, "id">' is not assignable to type 'myType'.
        Types of property 'id' are incompatible.
          Type 'NonNullable<string | number>' is not assignable to type 'string'.
            Type 'number' is not assignable to type 'string'.ts(2322)

How can I fix this?


Solution

  • Your ID can apparently be a string or number:

      ID: { input: string | number; output: string; }
    

    But your resolver argument has it strongly typed to a string which TS correctly points out as an issue because that resolver can receive a number as per your scalar definition of ID. You need to make that work with string or number

    getS: async (_parent: unknown, { id }: { id: string | number }): Promise<GenericResponse<S>> => { ... }
    

    But to be honest, since you already assign Resolvers type to the whole resolvers object you should just be able to completely remove the inline types and it will be inferred:

    getS: async (_parent, { id }) => { ... } // `id` should automatically be inferred as string | number