[ ] Regression
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
I'm reopening #429 which was closed and locked.
@ResolveField does not work for @InterfaceType and that's a very serious limitation.
@ResolveField should be supported for @InterfaceType
type-graphql introduced support for this a while ago, but it seems that in @nestjs/graphql they still don't work.
Relevant PR: https://github.com/MichalLytek/type-graphql/pull/579
From what I understand, @nestjs/graphql forked away from type-graphql.
@InterfaceType()
class Foo {
user: User
}
@ObjectType({ implements: Foo })
class Bar { ... }
@ObjectType({ implements: Foo })
class Baz { ... }
@ObjectType({ implements: Foo })
class Qux { ... }
@Resolver(of => Foo)
class Resolver {
@ResolveField(type => User)
user() { ... }
}
The above doesn't work, so you cannot populate user without creating separate resolvers for each object type, and duplicating it in each one.
The motivation has been discussed several times and is mostly related to code reuse, related issues:
https://github.com/MichalLytek/type-graphql/issues/260
https://github.com/MichalLytek/type-graphql/issues/261
I was able to find a workaround, but it isn't pretty:
function ResolverForUser<T extends Type<unknown>>(
classRef: T,
fieldName: string,
): any {
@Resolver(classRef)
class UserResolver {
@ResolveField(fieldName, () => User)
public user(
@Parent()
parent: any,
) {
// fetch user
}
//@ts-ignore
static get name() {
// need to override name to be unique, or resolver does not work
return `${classRef.name}Resolver`;
}
}
return UserResolver;
}
export const UserResolvers = [
Bar,
Baz,
Qux,
].map(type => ResolverForUser(type, "user"));
// then supply it to module providers like
@Module({
...,
providers: [...UserResolvers],
}
Hey everyone, just throwing my 2 cents in.
In addition to reducing the amount of duplicated code, this is also important because there is currently no way to define arguments on interface fields.
An implementation of this could use the interfaces metadata to find each type that implements the interface. Then it could register the resolver for each field in the implementing types, that don't already have a resolver for that field.
@kamilmysliwiec What's your opinion? Is there a better way to do this? A workaround that doesn't require changing the lib?
This should be available in 7.5.0 (resolvers for interfaces).
Example:
@Resolver((of) => IRecipe)
export class IRecipesResolver {
@ResolveField('interfaceResolver', () => Boolean)
interfaceResolver(
@Args('arg', { type: () => Number, nullable: true }) arg: number,
) {
return true;
}
}
where IRecipe is an @InterfaceType().
Most helpful comment
This should be available in 7.5.0 (resolvers for interfaces).
Example:
where
IRecipeis an@InterfaceType().