DEV Community

Cover image for How to Get Enums in Prisma Client: Import, Query
Mahdi BEN RHOUMA
Mahdi BEN RHOUMA

Posted on Originally published at iloveblogs.blog

How to Get Enums in Prisma Client: Import, Query

You’ve defined an enum in your Prisma schema, but when you try to use it in your application code, the generated client doesn’t seem to expose it anywhere. You’re not alone — the question “How to get enums in prisma client” on Stack Overflow shows many developers run into the same issue. The fix is straightforward: import the enum directly from @prisma/client and use it as both a TypeScript type and a runtime object.

  • Symptom: You can't find your Prisma schema enum in the generated client — no property on prisma, no auto-import.
  • Root cause: Prisma enums are exported as standalone types/values from @prisma/client, not as members of the PrismaClient instance.
  • Fix: Import the enum by name from @prisma/client (e.g., import { Role } from '@prisma/client').
  • Verification: Log Object.values(Role) and run a query that uses the enum — both should work without TypeScript errors.

What you’ll see

You open your editor, type prisma. and expect an enum like Role to appear in the autocomplete. It doesn’t. You try Prisma.Role and get a TypeScript error:

Property 'Role' does not exist on type 'PrismaClient<...>'.
Enter fullscreen mode Exit fullscreen mode

You might also see:

Cannot find module '@prisma/client' or its corresponding type declarations.
Enter fullscreen mode Exit fullscreen mode

if the client hasn’t been generated yet. The symptom is the same across any environment — local dev, CI, or production — whenever you attempt to reference a schema enum without the correct import.

Root cause

Prisma generates enums as standalone exports inside the @prisma/client package. They are not attached to the PrismaClient instance; they live as named exports alongside the client class. When you write import { PrismaClient } from '@prisma/client', you only get the client constructor. The enum is a separate export that you must import explicitly.

After running prisma generate, the enum is exported from @prisma/client as a const object with string literal values, and a corresponding type is derived from its keys. You don’t need to inspect the generated file; simply import it by name.

Because it’s a dual export (value and type), you can use Role as both a runtime object and a TypeScript type. But if you never import it, the compiler has no knowledge of it, and your code breaks.

The fix: Importing the generated enum from @prisma/client

The single change that resolves every variant of this problem is adding a named import for your enum:

import { PrismaClient, Role } from '@prisma/client';
Enter fullscreen mode Exit fullscreen mode

Now Role is available as a value (e.g., Role.USER) and as a type annotation (role: Role). The rest of this section covers the most common patterns you’ll need after that import.

Using enum values in Prisma queries

Once imported, you can pass enum members directly to create, update, findMany, and other query methods:

import { PrismaClient, Role } from '@prisma/client';

const prisma = new PrismaClient();

const user = await prisma.user.create({
  data: {
    email: 'alice@example.com',
    role: Role.ADMIN,   // ✅ no string literal
  },
});

const admins = await prisma.user.findMany({
  where: { role: Role.ADMIN },
});
Enter fullscreen mode Exit fullscreen mode

TypeScript will enforce that only valid enum members are used, preventing typos like 'admn'.

Getting all enum values at runtime

To populate a dropdown, build a validation schema, or iterate over possible values, use Object.values():

import { Role } from '@prisma/client';

const allRoles = Object.values(Role);
// ['USER', 'ADMIN']
Enter fullscreen mode Exit fullscreen mode

If you need a human-readable label, create a mapping object:

import { Role } from '@prisma/client';

const roleLabels: Record<Role, string> = {
  USER: 'Regular User',
  ADMIN: 'Administrator',
};
Enter fullscreen mode Exit fullscreen mode

Displaying enum values in a dropdown or select input

In a React component, you can map over the values:

import { Role } from '@prisma/client';

const roleOptions = Object.values(Role).map((value) => ({
  value,
  label: value.charAt(0) + value.slice(1).toLowerCase(), // "User", "Admin"
}));

<select>
  {roleOptions.map((opt) => (
    <option key={opt.value} value={opt.value}>{opt.label}</option>
  ))}
</select>
Enter fullscreen mode Exit fullscreen mode

This keeps the UI in sync with the schema — adding a new enum value in schema.prisma and regenerating automatically updates the dropdown.

Validating enum inputs in API routes

When receiving data from a client, never trust that the string matches your enum. Use a validation library like Zod to parse and narrow the type. Here’s a complete example using Express:

import { z } from 'zod';
import { Role } from '@prisma/client';
import { Request, Response } from 'express';

const roleSchema = z.nativeEnum(Role);

// Example Express route
app.post('/api/users', (req: Request, res: Response) => {
  const parsed = roleSchema.safeParse(req.body.role);
  if (!parsed.success) {
    return res.status(400).json({ error: 'Invalid role' });
  }
  // parsed.data is of type Role
  // continue with Prisma query...
});
Enter fullscreen mode Exit fullscreen mode

This pattern catches invalid strings before they reach the database. For other frameworks (Next.js, Fastify, etc.), adapt the function signature accordingly.

Mapping Prisma enums to PostgreSQL enum types

If your PostgreSQL database uses a native enum type, you can map it in the Prisma schema with the @map attribute:

enum Role {
  USER
  ADMIN

  @@map("user_role")
}

model User {
  id    Int  @id @default(autoincrement())
  role  Role @default(USER)
}
Enter fullscreen mode Exit fullscreen mode

Prisma will use the PostgreSQL enum user_role for the column. You still import and use Role from @prisma/client exactly as before. When you need to alter the database enum (e.g., add a value), you’ll write a migration with ALTER TYPE … ADD VALUE. I cover that process in detail in Supabase Enums: ALTER TYPE ADD VALUE in Migrations.

Updating Prisma schema enums and regenerating

After you add, remove, or rename an enum value in schema.prisma, you must regenerate the client:

npx prisma generate
Enter fullscreen mode Exit fullscreen mode

If you skip this step, the TypeScript types will be out of sync, and you’ll get errors like Property 'NEW_VALUE' does not exist on type 'Role'. In a CI pipeline, always run prisma generate before type-checking.

Verify the fix

Create a small script to confirm everything is wired correctly:

// verify-enum.ts
import { PrismaClient, Role } from '@prisma/client';

const prisma = new PrismaClient();

async function main() {
  // 1. Runtime values are accessible
  console.log('All roles:', Object.values(Role));

  // 2. Query works without type errors
  const user = await prisma.user.findFirst({
    where: { role: Role.ADMIN },
  });
  console.log('Admin user:', user?.email);
}

main()
  .catch(console.error)
  .finally(() => prisma.$disconnect());
Enter fullscreen mode Exit fullscreen mode

Run it with npx ts-node verify-enum.ts. You should see the array of enum values and either a user record or undefined — no TypeScript or runtime errors.

If you still see Cannot find module '@prisma/client', make sure you’ve installed @prisma/client and run npx prisma generate. If you’re in a monorepo, verify that the import path resolves to the correct node_modules.

Why this happens (and how to avoid it next time)

The confusion arises because PrismaClient instance methods don’t show exported types in autocomplete. When you run prisma generate (tested with Prisma 5.20), the output includes Role as a standalone export — you can verify by opening node_modules/.prisma/client/index.d.ts and searching for export const Role. The Prisma namespace (from import type { Prisma } from '@prisma/client') offers helper types like Prisma.UserCreateInput, but enums are not nested there; they are flat exports. You import Role directly — not from PrismaClient and not from the Prisma namespace.

To prevent regressions, add a lint rule that flags raw string literals where an enum is expected. For example, with @typescript-eslint/no-restricted-syntax you can forbid role: 'ADMIN' and enforce role: Role.ADMIN. Also, include prisma generate in your postinstall script so the client is always fresh after dependency installation.

FAQ

How do I import a Prisma enum in my Node.js code?

Import it directly from @prisma/client. For an enum named Status in your schema, write import { Status } from '@prisma/client'. The import provides both the TypeScript type and the runtime object with all member values.

Why can’t I access my enum values from the Prisma client?

Prisma enums are not properties of the PrismaClient instance. They are standalone exports from the @prisma/client module. You must import them explicitly. Also, if you haven’t run prisma generate after adding the enum to your schema, the client won’t contain the new type.

Can I use Prisma enums in my frontend code?

Yes, as long as your frontend has access to the @prisma/client package (e.g., in a monorepo or by sharing the generated types). Import the enum and use it for dropdowns, validation, or type annotations. Be mindful of bundle size — tree-shaking will remove unused exports.

What happens if I add a new value to a Prisma enum in production?

You must run a database migration to add the value to the underlying PostgreSQL enum (if using native enums) and then regenerate the Prisma client. Deploy the migration first, then the updated application code. If you deploy the code before the migration, queries using the new value will fail with a database error.

Related


Originally published at https://www.iloveblogs.blog

Top comments (0)