Leveraging The Prisma Client API for Type Safety

Here at Arcus Digital we use typescript on all of our projects. 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. Fortunately, our preferred database abstraction layer, Prisma, offers a built-in solution for typing responses. For the purpose of this blog post, let's consider a simple example: a blog website with a basic 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:

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 truly lovely way.

async function posts() {
  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. Just superb. 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, Nick