lutaev
lutaev

Reputation: 337

TypeGraphql Field and Arg decorators using custom type

I'm trying to build a resolver using type-graphql library and found that I can't define custom argument type. Here is my code:


type Hits = { [K: string]: string | number }

@Resolver()
export default class SearchResolver {
  @Query(() => [String], { nullable: true })
  @UseMiddleware(isAuthenticated)
  async searchAssetList(@Arg('hits') hits: Hits) {
    return [];
  }
}

I got an error:

NoExplicitTypeError: Unable to infer GraphQL type from TypeScript reflection system. You need to provide explicit type for argument named 'hits' of 'searchAssetList' of 'SearchResolver' class.

I also tried to define an input class:

type Hits = { [K: string]: string | number }

@ObjectType()
class SearchListInput {
  @Field(() => GraphQLObjectType)
  hits: Hits;
}

@Resolver()
export default class SearchResolver {
  @Query(() => [String], { nullable: true })
  async searchAssetList(@Arg('input') input: SearchListInput) {
    return []
  }
}

and got another error:

UnhandledPromiseRejectionWarning: Error: Cannot determine GraphQL input type for argument named 'input' of 'searchAssetList' of 'SearchResolver' class. Is the value, that is used as its TS type or explicit type, decorated with a proper decorator or is it a proper input value?

Replacing @ObjectType with @InputType also doesn't help. How to define decorators like @Field, @Arg correctly?

Any help is appreciated. Thanks.

Upvotes: 0

Views: 2688

Answers (2)

Barnoukh Youssef
Barnoukh Youssef

Reputation: 36

I had exactly the same issue, a couple of days ago, and I solve it using GraphQLScalarType by creating my own custom type here how to do it

import { GraphQLScalarType} from "graphql";

export const GraphQLAny = new GraphQLScalarType({
    name: 'Any',
    serialize: (value) => value,
    parseValue: (value) => value,
    parseLiteral: (ast) => ast
});

and in your class you can use your customTpe like this:

@ObjectType()
class SearchListInput {
  @Field(() => GraphQLAny)
  hits: typeof GraphQLAny;
}

Upvotes: 0

Luis Monsalve
Luis Monsalve

Reputation: 160

I think you are trying to have an Arg of an array whit numbers and strings in that case you should do

@InputType()
class HitsInput
{
    @Field()
    Hits: [number | string];
}

@Resolver()
export default class SearchResolver {
  @Query(() => [String], { nullable: true })
  async searchAssetList(@Arg('input') input: HitsInput) {
    return []
  }
}

if this is not the case and you want an object whit dynamic fields you need to define the object, let say if hits have Name and Id_Hits,

@InputType()
class HitsInput
{
    @Field()
    Id_Hits: number;

    @Field()
    Name: string;
}

@Resolver()
export default class SearchResolver {
  @Query(() => [String], { nullable: true })
  async searchAssetList(@Arg('input') input: HitsInput) {
    return []
  }
}

and if you want to have a dynamic args base in the user request I am not quite sure that it is possible, but it is possible to do this

@InputType()
class HitsInput
{
    [key: string]: any;
}

Upvotes: 1

Related Questions