Search code examples
typescriptnestjsnestjs-graphql

Validation of args passed to generic mutation in base resolver


Current behavior

  • I have a base class and some derived classes
  • There is a BaseResolver, which is inherited by the resolvers of the derived classes
  • Inside the BaseResolver, there is a create mutation
  • This create mutation takes in different arguments depending on the derived class
  • There is a create DTO for the base class, the create DTO of the derived classes inherit from this class
  • I pass the create DTO class of the derived class to the BaseResolver while inheriting it in the derived resolvers

Base resolver:

export function BaseResolver<
  T extends Type<BaseClass>,
  createClassDto extends Type<CreateBaseClassDto>,
>(classRef: T, createClassArgsDtoRef: createClassDto): any

Derived resolver:

@Resolver((of) => DerivedXClass)
export class DerivedXResolver extends BaseResolver(
  DerivedXClass,
  CreateDerivedXDto,
) 
  • I specify the type of the arguments as follows:
 async createMutation(
      @Args({ type: () => createClassArgsDtoRef })
      args: Type<CreateBaseClassDto>,
    )
  • The arguments are not being validated at all

Minimum reproduction code

It has the steps to reproduce and the expected behaviour.

https://github.com/snigdha920/nestjs-validation-args


Solution

  • I'm sure there's probably a cleaner way to do this, but something hacky would look like

        @Mutation(() => Boolean, { name: `create${classRef.name}` })
        async createMutation(
          @Args({ type: () => createClassArgsDtoRef })
          args: // @ts-ignore
          createClassArgsDtoRef,
        ) {
          console.log('class is ', classRef.name);
          console.log('args captured are ', args);
          return true;
        }
      }
    

    Typescript essentially doesn't understand that what you pass here is in fact a class reference and it should be used as a type. There's probably a better way to set this, maybe even the use of a custom parameter decorator, but this works for now and satisfies general type usage to the best of my knowledge