How to build Drizzle explicit types

Call me dumb, but I don't fully get how we can have explicit types that we can easily
import
in the various components of the application.

I've worked few months with Prisma, and over there you have the engine that's able to generate all the types that your queries will generate and you can import them as needed.

As far as I can see, Drizzle ORM does not do that. While I feel that what it does is still great, they provide you the
type
definition with all the props properly typed but you don't have a way to import them.

You rely on the implicit types that the query will expose.

Don't you think that's kind of limiting your ability to have explicit types that you can import in your components?

A quick example

Let's say you have a component that display the values from the following query:

export async function getRoleBySlug(slug: string) {
  return await db.query.roles.findFirst({
    where: (role, { eq }) => eq(role.slug, slug),
    });    
}


If I hover on the function name with VS Code I get the following message:

function getRoleBySlug(slug: string): Promise<{
    id: number;
    name: string;
    slug: string;
} | undefined>


While this is semantically correct, how do you type the prop inside the component that will consume the result from this query?

Are you doing something like this?

type Role = {
    id: number;
    name: string;
    slug: string;
}

export default function DisplayRole({ role }: { role: Role }) { 
    // Your component code...
}


I mean, doesn't it feel "too much"?

An approach with drizzle-zod

I've started to use drizzle-zod since I already use zod inside my application, and now in each of my schemas I add the following:

import { createInsertSchema, createSelectSchema } from 'drizzle-zod';

const roles = pgTable('roles', {
  id: serial('id').primaryKey(),
  slug: varchar('slug', { length: 255 }).unique().notNull(),
  name: varchar('name', { length: 255 }).notNull(),
});

export const rolesInsertSchema = createInsertSchema(roles);
export const rolesSelectSchema = createSelectSchema(roles);

export default roles;


And then I find myself generating the types inside my index.d.ts file like so:

import type { roleSelectSchema } from '@/src/drizzle/schema/roles';

export type Role = z.infer<typeof roleSelectSchema>;


So now I can go back to the previous <DisplayRole /> component and import the Role type.

Do you have a better approach to make TypeScript fully working? Is probably my project not configured well enough to work with Drizzle?
Was this page helpful?