DEV Community

Cover image for A real solution for client-side Prisma types
Stuart Haas
Stuart Haas

Posted on

A real solution for client-side Prisma types

We recently migrated an internal application from Sequelize to Prisma. I love the way we can observe our entire database schema with a single file and generate actual sql files for migrations. Recently I figured out a simple way to import Prisma types on the client-side. We are using Turbo repo and one of our devs ended up using a generator with the Prisma schema to create types for the front-end. I don't like redundancy so I did some digging. Here's what I did to solve the issue.

root directory snapshot

VS Code project directory

pnpm-workspace.yaml

packages:
  - "client"
  - "server"
  - "prisma"
  - "packages/*"
Enter fullscreen mode Exit fullscreen mode

package.json

{
  "name": "tutorial",
  "private": true,
  "version": "0.0.0",
  "scripts": {
    "dev": "turbo run dev --parallel",
    "dev:client": "turbo run dev --filter=!server --parallel",
    "build": "turbo run build",
    "build:client": "turbo run build --filter=!server",
    "start": "turbo run start"
  },
  "devDependencies": {
    "turbo": "^1.11.1"
  }
}

Enter fullscreen mode Exit fullscreen mode

turbo.json

{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "dev": {
      "dependsOn": ["db:generate"],
      "cache": false
    },
    "build": {
      "dependsOn": ["db:generate"],
      "outputs": ["dist/**"],
      "cache": false
    },
    "start": {
      "dependsOn": ["^build"],
      "cache": false
    },
    "db:generate": {
      "cache": false
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

prisma directory snapshot

VS Code prisma directory

prisma/package.json

{
  "name": "prisma",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "db:generate": "prisma generate",
    "db:push": "prisma db push",
    "db:seed": "ts-node seed.ts"
  },
  "dependencies": {
    "@prisma/client": "5.7.1",
    "prisma": "^5.5.2",
    "ts-node": "^10.9.1"
  }
}
Enter fullscreen mode Exit fullscreen mode

prisma/index.ts

export * from '@prisma/client';
Enter fullscreen mode Exit fullscreen mode

client/package.json ➡️ devDependencies

...
"prisma": "workspace:*",
...
Enter fullscreen mode Exit fullscreen mode

client/tsconfig.json

{
  "extends": "tsconfig/vue.json",
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "prisma": ["../prisma/node_modules/@prisma/client/*"]
    },
    "types": [
      "../prisma/node_modules/@prisma/client/index.d.ts",
      "../prisma/node_modules/@prisma/client/runtime/library.d.ts"
    ]    
  },
  "include": ["src"],
  "exclude": ["dist", "node_modules"]
}
Enter fullscreen mode Exit fullscreen mode

server/package.json ➡️ dependencies

...
"prisma": "workspace:*",
...
Enter fullscreen mode Exit fullscreen mode

server/tsconfig.json

{
  "extends": "tsconfig/node.json",
  "compilerOptions": {
    "baseUrl": ".",
    "strict": false,
    "paths": {
      "@/*": ["src/*"],
      "prisma": ["../prisma/node_modules/@prisma/client/*"]
    },
    "types": [
      "../prisma/node_modules/@prisma/client/index.d.ts",
      "../prisma/node_modules/@prisma/client/runtime/library.d.ts"
    ]
  },
  "include": ["src"],
  "exclude": ["dist", "node_modules"]
}
Enter fullscreen mode Exit fullscreen mode

On the client we can import Prisma types like this:

import type { User } from 'prisma';
Enter fullscreen mode Exit fullscreen mode

Hover over User to verify that the types will resolve correctly.

Prisma User type import

On the server side we can create a new Prisma client instance like this:

import { PrismaClient } from 'prisma';

export const prisma = new PrismaClient();
Enter fullscreen mode Exit fullscreen mode

Hover over PrismaClient() to verify that it will resolve correctly.

PrismaClient import

Prisma doesn't include relationships with the generate types so we have to do this by hand. Here's a quick example.

prisma/index.ts

export * from '@prisma/client';

import type { User as $User, Role } from '@prisma/client';

export type User = {
  role: Role;
} & $User;
Enter fullscreen mode Exit fullscreen mode

Hover over User to verify that Role will be included in the type.

Prisma User type with Role

I imagine this will be helpful to many as I haven't found a direct answer for this elsewhere. If you questions or comments please feel free to share!

Top comments (0)