Leveraging The Prisma Client API for Type Safety
I like to use Typescript whenever possible. There are a lot of reasons for this. Developer experience, iteration speed, the list goes on and on. But the biggest reason is it reduces the chance of fatal errors in production. Its as simple as that.
One of the main challenges in this development approach is typing responses from requests, whether they are coming from an external API or an in-house database. One tool I've been reaching for more often is the Prima ORM. One of the main selling points for me is the tools it offers to generating types. Lets take a simple example for the purposes of this blog post: a blog website with a simple schema.
model User {
id String @id @default(cuid())
name String?
email String @unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
posts Post[]
comments Comment[]
}
model Post {
id Int @id @default(autoincrement())
title String
link String?
text String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
author User @relation(fields: [authorId], references: [id])
authorId String
comments Comment[]
}
model Comment {
id Int @id @default(autoincrement())
text String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
author User @relation(fields: [authorId], references: [id])
authorId String
post Post @relation(fields: [postId], references: [id])
postId Int
}
Out of the box Prisma will allow us to import the types of these models. For example we can simply import the User type, and it will be of this shape:
type User = {
id: string;
name: string | null;
email: string;
emailVerified: Date | null;
image: string | null;
}
Rad! However, you may notice that the type only includes fields that do not reference another table. What if we have a function that performs a join and returns an object that includes referenced fields? This is where the Prisma client comes to the rescue in a really cool way.
async function getPosts() {
const res = await prisma.post.findMany({
include: {
author: {
select: {
name: true,
image: true,
},
},
},
});
return res;
}
type PostArrayWithAuthor = Prisma.PromiseReturnType<typeof posts>;
Here, we need to retrieve all posts but want to include the author's name and image for the visual representation of the blog post. If we need to perform some action on this return type, Prisma provides a clean and easy-to-read tool to generate a type for the return of this promise. We can export it and use it anywhere, add helpers that use it in this file, etc. This seamless type safety extends from the database all the way to the client, requiring minimal setup.
I encourage you to explore their documentation for more insights into employing this pattern in your projects. It's exceptionally well-designed, with many valuable features like this throughout their product.
Cheers,
NHC