user9945420
user9945420

Reputation:

setup multiple return types for the NestJs GraphQL Query decorator

I want to create a GraphQL API using NestJs. As far as I understood I won't be throwing HTTP exceptions for invalid requests anymore. Therefore I think I have to create my own "error codes" I can send back to the client. So given this basic example

@ObjectType()
export class ErrorResponse {
  @Field()
  message: string;
}

I have a service function to return a user by its ID and I extended the return type to return an error object if the request was invalid.

  public async getUserById(id: number): Promise<ErrorResponse | User> {
    const user: User = await this.usersRepository.findOne(id);

    if (!user) {
      const errorResponse: ErrorResponse = new ErrorResponse();
      errorResponse.message = `User with ID ${id} does not exist`;
      return errorResponse;
    }

    return user;
  }

The resolver originally was something like

  @Query(() => User)
  public async user(@Args('id') id: number): Promise<ErrorResponse | User> {
    return this.usersService.getUserById(id);
  }

but as mentioned above it's also possible to return a ErrorResponse if the id does not exist. How can I design the Query decorator to provide multiple return types?

@Query(() => ErrorResponse | User)

won't do the trick and shows up with this error

The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.ts(2362)

Upvotes: 1

Views: 9068

Answers (3)

Michał Lytek
Michał Lytek

Reputation: 12077

If both ErrorResponse and User are an @ObjectType, you just need to "merge" them together using createUnionType.

https://docs.nestjs.com/graphql/unions-and-enums

Upvotes: 3

Samkit Jain
Samkit Jain

Reputation: 1

Answer by Michal seems to be working, but the link is redirecting to some spam post. Below link is official documentation for nestjs: https://docs.nestjs.com/graphql/unions-and-enums

Upvotes: 0

itssajan
itssajan

Reputation: 830

This is the solution that i came up for a similar situation. GraphQL expects single return ObjectType. First i created a common Object

@ObjectType()
export class MutationResult {
  @Field({ nullable: true })
  success?: boolean;

  @Field({ nullable: true })
  error?: boolean;
}

Then in the user module i created 2 objects types - User and UserResponse. On UserResponse i extened the common MutationResult Object

@ObjectType()
export class User {
  @Field(type => ID)
  id: string;

  @Field()
  name: string;
}

@ObjectType()
export class UserResponse extends MutationResult {
  @Field()
  result: User;
}

Now in query you can do this

mutation {
  addUser(name: "Test") {
    success,
    error,
    result {
      name
    }
  }
}

Upvotes: 3

Related Questions