Почему TypeScript — это не просто мода, а необходимость
Когда в 2012 году Microsoft представила TypeScript, мало кто верил, что надстройка над JavaScript станет стандартом индустрии. Сегодня TypeScript — это не просто «ещё один язык», а полноценная экосистема, которая меняет подход к разработке. По данным State of JS 2023, более 70% опрошенных разработчиков используют TypeScript в своих проектах, и эта цифра продолжает расти.
Но дело не только в статической типизации. Настоящая магия TypeScript раскрывается через библиотеки, которые используют его возможности на 100%. Забудьте про скучные «обёртки» для JavaScript-пакетов — мы поговорим о настоящих TypeScript-native инструментах, которые заставят ваш код петь.
В этой статье мы разберём самые интересные и полезные библиотеки TypeScript, которые стоит добавить в свой арсенал в 2024 году. От валидации данных до работы с базами данных — приготовьтесь удивляться.
Zod: король валидации данных
Если вы когда-нибудь писали код для проверки входных данных вручную, вы знаете, как это утомительно. Zod решает эту проблему элегантно и типизированно.
Почему Zod, а не Joi или Yup?
Главное преимущество Zod — это TypeScript-first подход. Все схемы автоматически выводят типы, и вам не нужно дублировать типы вручную. Никакого typeof, никаких интерфейсов, которые нужно синхронизировать с валидаторами.
import { z } from 'zod';
// Создаём схему
const UserSchema = z.object({
name: z.string().min(2, 'Имя должно быть длиннее 2 символов'),
email: z.string().email('Некорректный email'),
age: z.number().int().positive().optional(),
role: z.enum(['admin', 'user', 'moderator']).default('user'),
});
// Автоматически получаем тип
type User = z.infer<typeof UserSchema>;
// { name: string; email: string; age?: number; role: "admin" | "user" | "moderator" }
// Валидация данных
const result = UserSchema.safeParse({
name: 'Анна',
email: 'anna@example.com',
age: 25,
});
if (!result.success) {
console.error(result.error.errors);
} else {
// result.data — полностью типизированный объект
console.log(result.data.name); // string
}
Zod также поддерживает сложные схемы: объединения (union), пересечения (intersection), рекурсивные типы и даже трансформации данных. Это идеальный выбор для API-валидации, форм и конфигураций.
Prisma: ORM, который чувствует TypeScript
Работа с базами данных на TypeScript долгое время была компромиссом. TypeORM был громоздким, Sequelize — медленным, а Knex — недостаточно типизированным. Prisma изменил правила игры.
Как работает Prisma?
Вместо того чтобы писать модели в коде, вы описываете схему данных в специальном файле schema.prisma. Prisma генерирует TypeScript-клиент с полной поддержкой типов.
// schema.prisma
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
createdAt DateTime @default(now())
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
}
// Использование в коде
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
// Полностью типизированные запросы
async function getUsersWithPosts() {
const users = await prisma.user.findMany({
include: {
posts: {
where: { published: true },
select: { title: true, createdAt: true },
},
},
orderBy: { createdAt: 'desc' },
});
// users — массив с правильными типами
users.forEach(user => {
console.log(user.email, user.posts.length);
});
}
Prisma автоматически генерирует типы для всех моделей, включая вложенные запросы. Ошибки в названиях полей или типах данных отлавливаются на этапе компиляции, а не в рантайме. Это экономит часы отладки.
tRPC: API без REST и GraphQL
tRPC — это, пожалуй, самая инновационная библиотека в этом списке. Она позволяет создавать API между клиентом и сервером без написания REST-эндпоинтов или GraphQL-схем. Всё работает через обычные функции, но с полной типизацией.
Как это выглядит на практике?
// Серверная часть
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
const t = initTRPC.create();
const appRouter = t.router({
getUser: t.procedure
.input(z.string()) // валидация через Zod
.query(async (opts) => {
const user = await db.user.findUnique({ where: { id: opts.input } });
return user;
}),
createPost: t.procedure
.input(z.object({
title: z.string(),
content: z.string().optional(),
}))
.mutation(async (opts) => {
return await db.post.create({ data: opts.input });
}),
});
export type AppRouter = typeof appRouter;
// Клиентская часть
import { createTRPCReact } from '@trpc/react-query';
import type { AppRouter } from './server';
const trpc = createTRPCReact<AppRouter>();
function UserProfile({ userId }: { userId: string }) {
const { data, isLoading } = trpc.getUser.useQuery(userId);
if (isLoading) return <div>Загрузка...</div>;
// data — полностью типизированный объект User
return <h1>{data.name}</h1>;
}
tRPC автоматически синхронизирует типы между сервером и клиентом. Если вы измените процедуру на сервере, TypeScript на клиенте сразу укажет на ошибки. Никаких ручных спецификаций, никакого дублирования типов.
Valibot: лёгкая альтернатива Zod
Если Zod кажется вам слишком тяжёлым (а он действительно добавляет ~10KB в бандл), обратите внимание на Valibot. Эта библиотека построена на модульной архитектуре: вы импортируете только те валидаторы, которые используете.
Сравнение Zod и Valibot
import { object, string, number, email, minLength, safeParse } from 'valibot';
const UserSchema = object({
name: string([minLength(2, 'Имя слишком короткое')]),
email: string([email('Некорректный email')]),
age: number(),
});
type User = Output<typeof UserSchema>;
const result = safeParse(UserSchema, {
name: 'Анна',
email: 'anna@example.com',
age: 25,
});
if (result.success) {
console.log(result.output.name); // типизированный доступ
}
Valibot занимает всего 1KB в сжатом виде (против 10KB у Zod). Для проектов, где размер бандла критичен (например, мобильные приложения на React Native), это может быть решающим фактором.
Effect-TS: функциональное программирование на стероидах
Если вы знакомы с функциональными языками вроде Haskell или Scala, Effect-TS покажется вам родным