type-graphql icon indicating copy to clipboard operation
type-graphql copied to clipboard

can't override parent method

Open Morriz opened this issue 2 years ago • 3 comments

Describe the Bug According to the docs it should be possible to override parent methods in child resolvers. This seems not to work due to typing errors.

Let's say I override a generated crud resolver like this:

@Resolver()
class CustomUserResolver extends UserCrudResolver {
  // overriding UserCrudResolver.createUser to publish events:
  @Mutation({ name: 'createUser' })
  async createUser(
    @Ctx() ctx: any,
    @Info() info: GraphQLResolveInfo,
    @Args() args: UserCreateInput,
    @PubSub('USERS') publish: Publisher<UserCreateInput>,
  ): Promise<User> {
    // let parent handle original intent
    const ret = await UserCrudResolver.prototype.createUser.call(this, ctx, info, args)
    // then publish as successful
    await publish({ email: args.email })
    // and return original
    return ret
  }
  @Subscription({
    topics: 'USERS',
  })
  newUser(@Root() { email }: UserNotification): UserNotification {
    info('New user onboard: ' + email)
    return { email }
  }
}

This will err:

Property 'createUser' in type 'CustomUserResolver' is not assignable to the same property in base type 'UserCrudResolver'.
  Type '(ctx: any, info: GraphQLResolveInfo, args: UserCreateInput, publish: Publisher<UserCreateInput>) => Promise<User>'

This also shows my intent: to add publication events to existing functions. I also have an issue with doing that through inheritance, and instead favor AOP approach for that. (See https://github.com/MichalLytek/type-graphql/discussions/1294)

Environment (please complete the following information):

  • OS: MacOS
  • Node 16.4.2
  • Package 1.1.1
  • TypeScript version 4.6.4

Morriz avatar Jun 10 '22 18:06 Morriz

I no longer see the need to intercept to achieve my goals, because your example shows how to tap into prisma subscriptions like this:

type UserNotification = {
  email: string
}

@Resolver()
class SubscriptionsResolver {
  @Subscription({
    subscribe: (root, args, context, info) => context.prisma.$subscribe.users({ mutation_in: [args.mutationType] }),
  })
  newUser(@Root() { email }: UserNotification): User {
    info('New user onboard: ' + email)
    return { email }
  }
}

But then I get an error which I don't see the cause of (as all the types are there afaik):

NoExplicitTypeError: Unable to infer GraphQL type from TypeScript reflection system. You need to provide explicit type for 'newUser' of 'SubscriptionsResolver' class.

Morriz avatar Jun 10 '22 18:06 Morriz

type UserNotification

You need to make it a class with decorators.

MichalLytek avatar Jun 10 '22 19:06 MichalLytek

But in your example you also just provide the NotificationPayload as class, and the Notification as interface. In my example above I do the same. User is a class exported by your crud mechanism, while UserNotification is the interface.

Morriz avatar Jun 13 '22 07:06 Morriz