【问题标题】:Returning unions in TypeGraphQL在 TypeGraphQL 中返回联合
【发布时间】:2021-04-21 07:05:35
【问题描述】:

所以我有这个代码:

const getAllUsers = ({
  Model, options,
}) => Model.find(options).catch((e) => {
  throw e;
});

@ObjectType({ description: "User model" })
@Entity()
export class UserModel extends BaseEntity {
    ...
}

@ObjectType()
class Error {
  constructor(data: {message: string, code: number}) {
    this.message = data.message;
    this.code = data.code;
  }
  @Field(() => Int)
  code: number;
  @Field(() => String)
  message: string;
}

@ObjectType()
class Success {
  @Field(() => [ UserModel ])
  users: [UserModel];
}

const UserResponseType = createUnionType({
  name: "UserResponseType",
  types: () => [
    Success,
    Error,
  ] as const,
});

@Query(() => [ UserResponseType ])
async getAllUsers(): Promise<typeof UserResponseType> {
  const errors = await Promise.resolve([
    new Error({
      code: 501,
      message: "test",
    }),
  ]);
  const users = await getAllUsers({
    Model: UserModel,
    options: {
      ...
    },
  }).catch((e) => e);
  return {
    errors,
    success: users,
  };
}

我要做的就是返回错误或成功,以便我可以在查询中执行此操作:

query getAllUsers {
  getAllUsers {
    ... on Success {
      user {
        id
        email
      }
    }
    ... on Error {
      code
      message
    }
  }
}

但现在我得到了:

TS2322: Type '{ errors: Error[]; success: any; }' is not assignable to type 'Error | Success'.
Object literal may only specify known properties, and 'errors' does not exist in type 'Error | Success'.

我试图复制(https://typegraphql.com/docs/unions.html#docsNav)[这个例子) 那么如何才能实现上述的查询能力呢?

【问题讨论】:

  • 为什么非标准错误处理?错误不应作为数据返回
  • 现在这是一个很大的学习曲线的一部分。我应该如何返回错误?在 REST 中,我会将它们返回为 res.json({error:{code:5xx, message: "..."})。在 GraphQL 中我还能如何处理它?这也是我在网上找到的wjat
  • 优点/缺点...与中间件不兼容/记录/隐藏生产/等细节...apollographql.com/docs/apollo-server/data/errors...只是抛出一些错误类型的消息
  • @xadm 无法连接到数据库之类的异常?是的,只是抛出一个错误。像UserAlreadyExists 这样的域“错误”?使用专用的对象类型和联合返回类型,因此您在客户端的响应中有一个类型安全的 swich-case。

标签: javascript typescript graphql typegraphql


【解决方案1】:

async getAllUsers()返回的值与声明的返回值Promise&lt;typeof UserResponseType&gt;不匹配,导致TS2322错误。

该函数返回具有errorssuccess 属性的对象,但它应该返回ErrorSuccess 实例。像这样的东西应该可以工作:

import {
  createUnionType,  
  Field,
  Int,
  ObjectType,
  Query,
  Resolver,
} from "type-graphql";

@ObjectType({ description: "User model" })
export class UserModel {
  @Field()
  id: string;
}

@ObjectType()
class Error {
  @Field(() => Int)
  code: number;
  @Field(() => String)
  message: string;
}

@ObjectType()
class Success {
  @Field(() => [UserModel])
  users: UserModel[];
}

const UserResponseType = createUnionType({
  name: "UserResponseType",
  types: () => [Success, Error] as const,
  resolveType: (value) => {
    if ("code" in value) {
      return Error;
    }
    if ("users" in value) {
      return Success;
    }
    return undefined;
  },
});

@Resolver()
export class UserResolver {
  @Query(() => UserResponseType)
  async getAllUsers(): Promise<typeof UserResponseType> {
    const error: Error = {
      code: 501,
      message: "test",
    };
    const success: Success = { users: [{ id: "1" }, { id: "2" }] };
    return success;
  }
}

现在运行以下查询将返回用户的 ID。如果将return success; 更改为return error;,查询将返回错误详细信息。

query getAllUsers {
  getAllUsers {
    ... on Success {
      users {
        id
      }
    }
    ... on Error {
      code
      message
    }
  }
}

【讨论】:

  • 请提供此类错误处理的 Apollo(最流行的 graphql 客户端)+typescript 示例......以完成(不只是 BE)。
  • 您有什么特别感兴趣的吗?我可以尝试创建一个可运行的后端和前端,但这需要更多的努力。 blog.logrocket.com/… 似乎更详细地介绍了该主题,该主题在问题 cmets 中进行了讨论。不提倡或批评这种错误处理方法(就本答案而言,错误和成功可能是橙色和苹果),只是想帮助解决问题中的 TS2322 错误。
猜你喜欢
  • 2020-12-20
  • 2021-08-07
  • 1970-01-01
  • 2021-03-20
  • 2022-10-19
  • 2021-11-07
  • 1970-01-01
  • 2022-12-18
相关资源
最近更新 更多