Using this package? Please consider donating to support my open source work ❤️
Help prisma-json-types-generator grow! Star and share this amazing repository with your friends and co-workers!
Important
Maintenance Status Update: This project's maintenance approach has changed. Please see this issue for details about what this means for users and the project's future.
Generate your prisma client with strict JSON types and String literals!
- Installation
- Configuration
- Quick Start
- Typing
StringFields (Enums) - Advanced Typing
- Validating Types at Runtime
- Limitations
- How It Works
- License
Supercharge your @prisma/client by adding strong, custom types to Json and String fields. This generator enhances type safety by replacing Prisma's default JsonValue with your own TypeScript types, ensuring data conforms to your schema before it even reaches the database.
It works with all database drivers supported by Prisma (PostgreSQL, MySQL, SQLite, etc.) without affecting any runtime code.
- Strongly Typed
Json: Define complex object shapes for yourJsonfields. - String-Based Enums: Type
Stringfields to create enums without needing native database enums. - Full Type-Safety: Get autocomplete, intellisense, and compile-time checks for your data structures.
- Zero Runtime Overhead: All transformations happen at generation time.
- Flexible Typing: Define types globally in a namespace or inline directly in your schema.
Install the package as a development dependency in your project.
npm install -D prisma-json-types-generatorYou can configure the generator in your schema.prisma file.
generator json {
provider = "prisma-json-types-generator"
namespace = "PrismaJson"
allowAny = false
// etc...
}| Option | Description | Default |
|---|---|---|
namespace |
The global namespace where your custom types are defined. | "PrismaJson" |
clientOutput |
Path to the @prisma/client output directory. The generator usually finds this automatically, but you can specify it if needed (e.g., in complex monorepos). |
(auto-detected) |
allowAny |
If true, untyped Json fields will resolve to any. If false, they will resolve to unknown for stricter type safety. |
false |
useType |
Specifies a root type within your namespace to use as a fallback for all untyped Json fields. This adds an index signature [key: string]: any to the specified type. |
undefined |
Follow these three steps to get started.
-
Add the Generator to Your Schema
In your
schema.prismafile, add thejsongenerator block below the defaultclientgenerator.generator client { provider = "prisma-client-js" } generator json { provider = "prisma-json-types-generator" }
-
Define Your Custom Types
Create a type declaration file (e.g.,
src/types.ts) and ensure it's included in yourtsconfig.json. Define your types inside thePrismaJsonglobal namespace.// This file must be a module, so we include an empty export. export {}; declare global { namespace PrismaJson { // Define a type for a user's profile information. type UserProfile = { theme: 'dark' | 'light'; twitterHandle?: string; }; } }
-
Link Types in Your Prisma Schema
Use an AST comment (
/// [TypeName]) above aJsonfield in yourschema.prismato link it to your custom type.model User { id Int @id @default(autoincrement()) email String @unique /// [UserProfile] profile Json }
Now, run npx prisma generate. The profile field on the User model will be strongly typed!
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function updateUserProfile() {
const user = await prisma.user.update({
where: { id: 1 },
data: {
profile: {
theme: 'dark'
// twitterHandle is optional
}
}
});
// user.profile is now fully typed as UserProfile!
console.log(user.profile.theme); // 'dark'
}You can use the same technique to type String fields, which is perfect for creating "string enums" without using Prisma's native enum type. This is useful for maintaining a set of allowed values directly in your application code.
Use the inline type syntax (/// ![Type]) for this.
model Post {
id Int @id @default(autoincrement())
title String
/// !['draft' | 'published' | 'archived']
status String @default("draft")
}After generating, post.status will be correctly typed as 'draft' | 'published' | 'archived'.
The generator offers two ways to define types:
- Namespace-based (
/// [TypeName]): References a type from thePrismaJsonnamespace. Best for complex, reusable types. - Inline (
/// ![Type]): Defines the type directly in the schema. Best for simple, one-off types like enums or basic objects.
model Product {
id Int @id
// Namespace-based type
/// [ProductMeta]
meta Json?
// Array of namespace-based types
/// [Tag]
tags Json[]
// Inline union type (enum)
/// !['physical' | 'digital']
type String
// Inline object type
/// ![{ width: number; height: number }]
dimensions Json
}export {};
declare global {
namespace PrismaJson {
type ProductMeta = {
sku: string;
stock: number;
};
type Tag = {
id: string;
name: string;
};
}
}This generator provides compile-time type safety, not runtime validation. You can, however, share types from a runtime validation library like Zod to create a single source of truth for your data structures.
The principle is simple:
- Define your schema using Zod.
- Infer the static TypeScript type from that schema.
- Expose the inferred type within the
PrismaJsonnamespace.
This pattern gives you both runtime validation and compile-time type safety from a single definition.
First, define your model in schema.prisma.
model User {
id Int @id @default(autoincrement())
/// [UserPreferences]
preferences Json
}Then, define the Zod schema and expose its inferred type in your TypeScript definitions file.
import { z } from 'zod';
// 1. Define the Zod schema as the source of truth.
export const UserPreferencesSchema = z.object({
theme: z.enum(['light', 'dark']),
language: z.string().optional()
});
// 2. Expose the inferred type to Prisma.
declare global {
namespace PrismaJson {
type UserPreferences = z.infer<typeof UserPreferencesSchema>;
}
}This same principle can be applied to other validation libraries like TypeBox or Yup that allow for static type inference.
- Complex Filters: To preserve functionality, types like
JsonFilterandJsonWithAggregatesFilterremain untyped. - Prisma Version: This generator supports Prisma v5+ and generator v3+.
- Known Gaps: If you find any
Jsonfields that are not being typed correctly, please open an issue.
This tool operates as a standard Prisma generator. When npx prisma generate runs, the generator receives the Data Model Meta Format (DMMF), which contains your full schema, including the AST comments. After prisma-client-js finishes, this generator targets its output declaration file (e.g., index.d.ts) and parses it into an Abstract Syntax Tree (AST) using the TypeScript Compiler API.
It then traverses this AST, and for each property signature in a model, it cross-references the DMMF to find a corresponding type comment. If a match is found, it performs a direct AST transformation, replacing the original type node (like Prisma.JsonValue or string) with a new node representing your custom type. Finally, the modified AST is printed back into TypeScript code, overwriting the original declaration file. This entire process occurs at build time and adds no runtime overhead. For a deeper dive, see the core implementation.
Licensed under the MIT. See LICENSE for more informations.
