dotansimha/graphql-code-generator

TypeScript Resolvers: Easier way to get possible resolve types for interfaces

Open

#6443 opened on Aug 8, 2021

View on GitHub
 (3 comments) (2 reactions) (0 assignees)TypeScript (10,341 stars) (1,295 forks)batch import
corehelp wantedkind/enhancement

Description

Is your feature request related to a problem? Please describe.

If you have an interface Document and multiple types implementing it, say Article, Thesis and Other, then the typescript resolvers generated looks similar to

export type DocumentResolvers<ContextType = Context, ParentType extends ResolversParentTypes['Document'] = ResolversParentTypes['Document']> = ResolversObject<{
  __resolveType: TypeResolveFn<'Article' | 'Thesis' | 'Other', ParentType, ContextType>;
  id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
  ....
}>;

As one can see, the implementing types are listed explicitly in the definition of the __resolveType function. Thus, they cannot easily be reused, which is mildly annoying if you want/need to use another function to return exactly one of the options (say because you need to parse or check other data to determine which of the types should be returned). A function like this would currently be annotated like

parse(input: any): 'Article' | 'Thesis' | 'Other'

This is prone to break in the future if other types implementing the interface are added, and leads to code duplication.

Describe the solution you'd like

Extract the possible type names to a separate type. Maybe even auto-generating something like

const DocumentResolveTypes = ['Article' | 'Thesis' | 'Other'] as const;
type DocumentResolveTypes = typeof DocumentResolveTypes [number];

so that one can easily iterate over the possible types.

Describe alternatives you've considered I'm currently using the following code as a work-around.

type ResolveFnc<TResolver extends ResolversObject<unknown>> =
  TResolver extends {
    __resolveType: infer T
  }
    ? T
    : never

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : unknown
/**
 * Type to extract the resolve type from a resolver for unions / interfaces.
 */
type ResolveType<TResolver extends ResolversObject<unknown>> = ReturnType<
  ResolveFnc<TResolver>
>

ResolveType<DocumentResolvers> // 'Article' | 'Thesis' | 'Other'

Contributor guide