| undefined on tRPC procedures

This is a pretty noob question about typescript but a lot of the tRPC return types union a undefined type. Is there a better way of dealing with this linting error besides casting it to the type or giving it a conditional back up like
foo || ""
foo || ""
28 Replies
whatplan
whatplan2y ago
can you send the function on your backend where this mutation is defined
MoltenFuzzy
MoltenFuzzyOP2y ago
deleteOne: protectedProcedure
.input(z.object({ id: z.string() }))
.mutation(async ({ ctx, input }) => {
const post = await ctx.prisma.post.findUnique({
where: { id: input.id },
select: { authorId: true, images: true },
});
// backend validation for user authorization to delete post
if (post?.authorId !== ctx.session.user.id) {
throw new TRPCError({
code: "CONFLICT",
message: "You are not authorized to delete this post",
});
}

// delete images from s3 bucket
for (const image of post.images) {
s3.deleteObject(
{
Bucket: env.AWS_BUCKET_NAME,
Key: `${image.userId}/${image?.postId as string}/${image.id}`,
},
(err) => {
if (err) {
console.log(err);
}
}
);
}

return ctx.prisma.post.delete({
where: { id: input.id },
});
}),
deleteOne: protectedProcedure
.input(z.object({ id: z.string() }))
.mutation(async ({ ctx, input }) => {
const post = await ctx.prisma.post.findUnique({
where: { id: input.id },
select: { authorId: true, images: true },
});
// backend validation for user authorization to delete post
if (post?.authorId !== ctx.session.user.id) {
throw new TRPCError({
code: "CONFLICT",
message: "You are not authorized to delete this post",
});
}

// delete images from s3 bucket
for (const image of post.images) {
s3.deleteObject(
{
Bucket: env.AWS_BUCKET_NAME,
Key: `${image.userId}/${image?.postId as string}/${image.id}`,
},
(err) => {
if (err) {
console.log(err);
}
}
);
}

return ctx.prisma.post.delete({
where: { id: input.id },
});
}),
i would need to change this then?
.input(z.object({ id: z.string() }))
.input(z.object({ id: z.string() }))
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
MoltenFuzzy
MoltenFuzzyOP2y ago
yea i noticed it was the prisma method findUnique that was unioning the undefined type, so changing it to findUniqueOrThrow and handling the error gives me the object without the undefined typing
whatplan
whatplan2y ago
Your input schema is defined as string so you must pass in a string if what your trying to pass in is string | undefined you need to handle the undefined case before you call the mutation this is a bad place to cast, typescript is telling you things could go wrong
MoltenFuzzy
MoltenFuzzyOP2y ago
ah okay
whatplan
whatplan2y ago
also you might consider awaiting the prisma call before the return statement you could never call the mutation at all, or do something like this and let the backend throw the error when prisma doesnt find anything with a matching id
deletePost.mutate({id: id ?? ""});
deletePost.mutate({id: id ?? ""});
MoltenFuzzy
MoltenFuzzyOP2y ago
another question, do all trpc procedures union an undefined?
MoltenFuzzy
MoltenFuzzyOP2y ago
getOne: publicProcedure
.input(z.object({ id: z.string() }))
.query(async ({ ctx, input }) => {
const post = await ctx.prisma.post.findUniqueOrThrow({
where: { id: input.id },
// joins the tables
include: {
author: true,
images: true,
// likedBy: true,
// dislikedBy: true,
},
});

await embedPostImageUrls([post as FullPost]);
return post;
}),
getOne: publicProcedure
.input(z.object({ id: z.string() }))
.query(async ({ ctx, input }) => {
const post = await ctx.prisma.post.findUniqueOrThrow({
where: { id: input.id },
// joins the tables
include: {
author: true,
images: true,
// likedBy: true,
// dislikedBy: true,
},
});

await embedPostImageUrls([post as FullPost]);
return post;
}),
whatplan
whatplan2y ago
really the question is does prisma return possibly undefined in hindsight this was actually wrong
MoltenFuzzy
MoltenFuzzyOP2y ago
it does not
MoltenFuzzy
MoltenFuzzyOP2y ago
as far as i know
whatplan
whatplan2y ago
in this case findUnqiueOrThrow will never be null, because prisma will throw if no matching item is found (what this means is the trpc query will error) so the reason it is type | undefined is because data is undefined when isError is true i think
whatplan
whatplan2y ago
this is helpful also
MoltenFuzzy
MoltenFuzzyOP2y ago
const {
data: postData,
isError,
error,
} = api.post.getOne.useQuery({ id: postId }, { enabled: true });

const { data: postComments } = api.comment.getAllFromPost.useQuery(
{ postId },
{ enabled: true }
);

if (isError) {
return <span>Error: {error.message}</span>;
}
const {
data: postData,
isError,
error,
} = api.post.getOne.useQuery({ id: postId }, { enabled: true });

const { data: postComments } = api.comment.getAllFromPost.useQuery(
{ postId },
{ enabled: true }
);

if (isError) {
return <span>Error: {error.message}</span>;
}
i added a check for errors, but the type | undefined is still there
MoltenFuzzy
MoltenFuzzyOP2y ago
MoltenFuzzy
MoltenFuzzyOP2y ago
this isnt really a big problem but adding checks to all my props isnt very pretty
whatplan
whatplan2y ago
this is a weak point of typescript it doesnt know that data + isError are connected I would just add
if (isError || !postData) {
return <span>Error: {error.message}</span>;
}
if (isError || !postData) {
return <span>Error: {error.message}</span>;
}
probably a better solution out there
MoltenFuzzy
MoltenFuzzyOP2y ago
hmm it still is giving me an error since the types dont match up with the props types, which i can union an undefined to fix that
MoltenFuzzy
MoltenFuzzyOP2y ago
whatplan
whatplan2y ago
my mistake i updated snippet
MoltenFuzzy
MoltenFuzzyOP2y ago
ah interesting thank you
whatplan
whatplan2y ago
np lmk if anything else comes up
MoltenFuzzy
MoltenFuzzyOP2y ago
bet tysm
cornflour
cornflour2y ago
so data will be undefined if its error or if the query is still loading if you check for both of those cases data will stop being undefined i believe (i havent tested with isLoading yet, but using status==="loading" and status==="error" worked for me before, so i assume it will be the same)
MoltenFuzzy
MoltenFuzzyOP2y ago
^ yup
Want results from more Discord servers?
Add your server