【发布时间】:2021-11-20 00:54:20
【问题描述】:
我正在尝试学习 Ben Awad 的 lireddit 教程。
在他制作教程的时候,可能对字段类型有不同的推论。
我正在尝试将字段添加到我的关系属性(将创建者字段添加到帖子),以便我可以访问该帖子记录上的创建者属性。
Ben 这样做如下:
@Field()
@ManyToOne(() => User, (user) => user.posts)
creator: User;
这对他有用。当我尝试这个时,我收到一条错误消息:
throw new errors_1.NoExplicitTypeError(prototype.constructor.name, propertyKey,参数索引,参数名称);
NoExplicitTypeError:无法从 TypeScript 推断 GraphQL 类型 反射系统。您需要为“创建者”提供显式类型 “发布”类。
当我查看 GraphQL docs 以了解如何为创建者提供显式类型时,我找不到类似的示例(简单到足以让我破译我可以应用的原则)。
我对文档感到困惑,因为有以下示例:
谁能看到我需要做什么才能要求将该字段识别为我可以读取的对象?
@ObjectType()
class Rate {
@Field(type => Int)
value: number;
@Field()
date: Date;
user: User;
}
我认为他们使用用户:用户的方式与我使用创建者:用户的方式相同。 Field() 不能和 ObjectType() 有相同的东西是有原因的吗?
我试过了:
@Field(() => [User])
@ManyToOne(() => User, (user) => user.posts)
creator: User;
这不会产生任何错误(代码也不会像 Ben 那样),直到我到达操场,在这种情况下,我无法返回用户数据 - 很明显这是错误的。也不清楚该数组是指用户对象上的属性数组还是用户数组(这也是错误的)。我可以从 GraphQL 文档中看到,应该可以将字段属性定义为对象类型,但我找不到说明如何做到这一点的示例。
我见过this post,这看起来像一个类似的问题,但我无法从建议的答案中看到如何将这些想法应用于这个问题。
我见过this post,它有类似的问题,并通过参考一个示例来回答,该示例显示如何编写查找关系的解析器,但我的解析器已经找到了 creatorId,所以我想也许我我没有在正确的地方寻找答案。
在我的帖子解析器中,我有:
import {
Resolver,
Query,
Arg,
Mutation,
InputType,
Field,
Ctx,
UseMiddleware,
Int,
FieldResolver,
Root,
ObjectType,
} from "type-graphql";
import { Post } from "../entities/Post";
import { MyContext } from "../types";
import { isAuth } from "../middleware/isAuth";
import { getConnection } from "typeorm";
@InputType()
class PostInput {
@Field()
title: string;
@Field()
text: string;
}
@ObjectType()
class PaginatedPosts {
@Field(() => [Post])
posts: Post[];
@Field()
hasMore: boolean;
}
@Resolver(Post)
export class PostResolver {
@FieldResolver(() => String)
textSnippet(@Root() post: Post) {
return post.text.slice(0, 50);
}
@Query(() => PaginatedPosts)
async posts(
@Arg("limit", () => Int) limit: number,
@Arg("cursor", () => String, { nullable: true }) cursor: string | null
): Promise<PaginatedPosts> {
// 20 -> 21
const realLimit = Math.min(50, limit);
const reaLimitPlusOne = realLimit + 1;
const qb = getConnection()
.getRepository(Post)
.createQueryBuilder("p")
.orderBy('"createdAt"', "DESC")
.take(reaLimitPlusOne);
if (cursor) {
qb.where('"createdAt" < :cursor', {
cursor: new Date(parseInt(cursor)),
});
}
const posts = await qb.getMany();
return {
posts: posts.slice(0, realLimit),
hasMore: posts.length === reaLimitPlusOne,
};
}
@Query(() => Post, { nullable: true })
post(@Arg("id") id: number): Promise<Post | undefined> {
return Post.findOne(id);
}
@Mutation(() => Post)
@UseMiddleware(isAuth)
async createPost(
@Arg("input") input: PostInput,
@Ctx() { req }: MyContext
): Promise<Post> {
return Post.create({
...input,
creatorId: req.session.userId,
}).save();
}
@Mutation(() => Post, { nullable: true })
async updatePost(
@Arg("id") id: number,
@Arg("title", () => String, { nullable: true }) title: string
): Promise<Post | null> {
const post = await Post.findOne(id);
if (!post) {
return null;
}
if (typeof title !== "undefined") {
await Post.update({ id }, { title });
}
return post;
}
@Mutation(() => Boolean)
async deletePost(@Arg("id") id: number): Promise<boolean> {
await Post.delete(id);
return true;
}
}
【问题讨论】:
标签: graphql typegraphql