type-graphql
type-graphql copied to clipboard
Support for __typename
Right now, for interfaces and unions, TypeGraphQL determines the type of the returned value using foo instanceof Foo
. This force to use class instances in every case where interfaces or unions are returned.
But this might be problematic in some cases, so it could just fallback to the __typename
based detection for the easier cooperation with plain objects.
Side note
Also resolveType
implementation in unions could be omitted as:
Optionally provide a custom type resolver function. If one is not provided, the default implementation will call isTypeOf on each implementing Object type.
Or maybe even better, for better compatibility, it should allow providing own resolveType
function in interface and union decorators/creators.
First of all, thanks @19majkel94 for adding this to your to-do list, it's a much-needed feature for our team. :)
Just chiming in to vocalise my support for both of the options you suggested: being able to set the __typename
field to inform TypeGraphQL of the concrete type of an interface/union would be sufficient for our needs, but your second suggestion of allowing us to provide a resolveType
function to the decorators/creators directly would be absolutely amazing!
@19majkel94 Until this new feature arrives: how would I provide the type in the current version?
From your initial comment I would assume, that TypeGraphQL can do this somehow magically by itself, but I get the error Abstract type MobileNumberCPS must resolve to an Object type at runtime for field...
in my implementation. I tried to provide __resolveType
and __isTypeOf
function that return the appropriate class name as string, but they don't get called.
This force to use class instances in every case where interfaces or unions are returned.
I don't understand this. Are you referring to the inner workings of TypeGraphQL or does my implementation need to provide a property or something in the class?
What do I need to do, that foo instanceof Foo
returns the correct and expected value?
Would be very grateful for any hint!
@maplesteve
// where interfaces or unions are returned.
@Query(returns => MyInterface)
myInterface() {
// use class instances
const response = new MyObjectType();
response.sampleField = "sampleFieldValue";
return response;
}
@19majkel94 any estimation of implementation?
I tried to use your alternative without success
import { Field, ID, ObjectType } from 'type-graphql';
@ObjectType()
export class ServiceProvider {
@Field(() => ID)
id!: string;
@Field()
name!: string;
@Field()
address!: string;
}
@ObjectType()
export class ServiceProviderA extends ServiceProvider {}
@ObjectType()
export class ServiceProviderB extends ServiceProvider {}
Here is my resolver (using nestjs):
@Resolver(ServiceProvider)
export class ServiceProviderResolvers {
constructor(private readonly searchService: SearchService) {}
@Query(() => [ServiceProvider])
async all(): Promise<(ServiceProviderA | ServiceProviderB)[]> {
const serviceProviders = await this.searchService.all();
const result = serviceProviders.map((serviceProvider) => {
if (serviceProvider.type === 'A') {
return Object.assign(new ServiceProviderA(), serviceProvider);
}
return Object.assign(new ServiceProviderB(), serviceProvider);
});
return result;
}
// Before using type-graphql with nestjs this was working:
// @ResolveProperty('__resolveType')
// resolveType(obj: ServiceProvider): string {
// return obj.type;
// }
}
I still get ServiceProvider
as __typename
instead of ServiceProviderA
or ServiceProviderB
.
Actually what would be super cool is to be able to do:
@ObjectType()
export class ServiceProvider {
@Field(() => ID)
id!: string;
@Field()
name!: string;
@Field()
address!: string;
@TypeName() // this decorator would say that it has to use this value as __typename
type!: string;
}
@TypeName()
// this decorator would say that it has to use this value as __typename
That's a great idea, you can reuse the property data instead of forcing to use spread operator and __typename
property of a new object.
Here is my resolver (using nestjs):
Nest has it's own runtime for resolving types and other things - TypeGraphQL is used only for SDL generation and nothing else.