PrismaJuniorTechnical
Как Prisma Client обеспечивает типобезопасность? Как генерируются типы?
Prisma генерирует TypeScript-типы из schema.prisma командой npx prisma generate. Типы аргументов (UserCreateInput) и результатов автоматически учитывают select/include, обеспечивая полную статическую типобезопасность.
Типобезопасность Prisma Client
Prisma генерирует полностью типизированный клиент на основе вашей схемы (schema.prisma). Генерация запускается командой npx prisma generate и создаёт TypeScript-типы в node_modules/@prisma/client (или в кастомном output-пути).
Как работает генерация типов
Prisma CLI читает prisma/schema.prisma и генерирует:
- Интерфейсы моделей (
User,Post, …) - Типы аргументов для каждого метода (
UserCreateInput,UserWhereUniqueInput, …) - Типы результатов с учётом
selectиinclude - Enum-типы, соответствующие
enumв схеме
Пример схемы и сгенерированных типов
// prisma/schema.prisma
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
author User @relation(fields: [authorId], references: [id])
authorId Int
}
import { PrismaClient, Prisma } from '@prisma/client';
const prisma = new PrismaClient();
// TypeScript знает, что result: User
const user = await prisma.user.findUnique({
where: { email: 'alice@example.com' },
});
// user: { id: number; email: string; name: string | null } | null
// select сужает тип до выбранных полей
const userWithName = await prisma.user.findUnique({
where: { id: 1 },
select: { id: true, name: true },
});
// userWithName: { id: number; name: string | null } | null
// include добавляет связанные данные к типу
const userWithPosts = await prisma.user.findUnique({
where: { id: 1 },
include: { posts: true },
});
// userWithPosts: (User & { posts: Post[] }) | null
Утилитарные типы Prisma
// Тип для создания пользователя
type CreateUserInput = Prisma.UserCreateInput;
// { email: string; name?: string | null; posts?: PostCreateNestedManyWithoutAuthorInput }
// Получить тип результата произвольного запроса
const userWithPostsQuery = Prisma.validator<Prisma.UserDefaultArgs>()({
include: { posts: true },
});
type UserWithPosts = Prisma.UserGetPayload<typeof userWithPostsQuery>;
// Полный тип: User & { posts: Post[] }
// Для функций, принимающих частичные данные
async function updateUser(id: number, data: Prisma.UserUpdateInput) {
return prisma.user.update({ where: { id }, data });
}
Подводные камни
- После любого изменения
schema.prismaнужно вручную запуститьnpx prisma generate— типы не обновляются автоматически. - В CI/CD шаг
prisma generateдолжен идти доtsc, иначе типы будут устаревшими. - Если используется кастомный
outputв генераторе, импортировать нужно из этого пути, а не из@prisma/client. select: { id: true }исключает все остальные поля из типа — обращение кresult.emailбудет ошибкой компиляции.- Тип поля с
?в схеме (name String?) будетstring | null, а неstring | undefined. - Enum в Prisma генерирует объект-константу и тип с одинаковым именем — не путайте импорт типа и значения.
- Prisma не генерирует типы для сырых SQL-запросов (
$queryRaw) — нужно приводить вручную черезas.
Common mistakes
- Путает Prisma Client API с гарантиями базы данных: индексы, блокировки и isolation level не создаются магически.
- Не объясняет, где в lifecycle находится типобезопасность Prisma Client.
- Не разделяет validation, authorization, business logic и persistence.
- Игнорирует ошибки, лимиты входных данных, observability и тестирование.
What the interviewer is testing
- Может объяснить типобезопасность Prisma Client на примере кода.
- Называет ключевые API: generated types, PrismaClient.
- Отделяет ORM/query builder поведение от реального поведения СУБД.
- Видит production-риски: безопасность, отказоустойчивость, логирование и тесты.