Работа с базами данных в TypeScript: PostgreSQL и MongoDB

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Работа с базами данных в TypeScript: PostgreSQL и MongoDB

TypeScript — это мощный язык программирования, который добавляет статическую типизацию в JavaScript. При разработке современных веб-приложений работа с базами данных является неотъемлемой частью. В этой статье мы рассмотрим, как эффективно работать с двумя популярными базами данных — реляционной PostgreSQL и документо-ориентированной MongoDB — используя TypeScript.

1. Подготовка окружения и выбор ORM

Прежде чем начать, необходимо настроить проект. Создайте новый проект Node.js с поддержкой TypeScript:

mkdir ts-database-demo
cd ts-database-demo
npm init -y
npm install typescript @types/node ts-node --save-dev
npx tsc --init

Для работы с базами данных мы будем использовать популярные библиотеки:

  • Prisma — современный ORM для PostgreSQL (и других SQL-баз)
  • Mongoose — ODM для MongoDB с отличной поддержкой TypeScript

Установите необходимые пакеты:

npm install prisma @prisma/client mongoose
npm install @types/mongoose --save-dev

2. Работа с PostgreSQL через Prisma

Prisma — это ORM, который автоматически генерирует типы TypeScript на основе вашей схемы базы данных. Это обеспечивает полную типовую безопасность.

2.1. Настройка Prisma

Инициализируйте Prisma в проекте:

npx prisma init

В файле prisma/schema.prisma определите модель данных:

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  name      String?
  posts     Post[]
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  published Boolean  @default(false)
  author    User     @relation(fields: [authorId], references: [id])
  authorId  Int
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

Создайте файл .env с строкой подключения:

DATABASE_URL="postgresql://user:password@localhost:5432/mydb"

Выполните миграцию:

npx prisma migrate dev --name init

2.2. CRUD-операции с TypeScript

Теперь напишем типизированный код для работы с базой данных. Создайте файл src/postgres.ts:

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

const prisma = new PrismaClient();

interface CreateUserInput {
  email: string;
  name?: string;
}

interface CreatePostInput {
  title: string;
  content?: string;
  authorId: number;
}

// Создание пользователя
async function createUser(data: CreateUserInput) {
  return await prisma.user.create({
    data: {
      email: data.email,
      name: data.name,
    },
  });
}

// Получение всех пользователей с постами
async function getUsersWithPosts() {
  return await prisma.user.findMany({
    include: {
      posts: true,
    },
  });
}

// Создание поста
async function createPost(data: CreatePostInput) {
  return await prisma.post.create({
    data: {
      title: data.title,
      content: data.content,
      authorId: data.authorId,
    },
  });
}

// Обновление пользователя
async function updateUser(id: number, data: Partial<CreateUserInput>) {
  return await prisma.user.update({
    where: { id },
    data,
  });
}

// Удаление пользователя
async function deleteUser(id: number) {
  return await prisma.user.delete({
    where: { id },
  });
}

// Пример использования
(async () => {
  try {
    const user = await createUser({
      email: 'ivan@example.com',
      name: 'Иван Иванов',
    });
    console.log('Создан пользователь:', user);

    const post = await createPost({
      title: 'Первая запись',
      content: 'Содержимое поста',
      authorId: user.id,
    });
    console.log('Создан пост:', post);

    const users = await getUsersWithPosts();
    console.log('Пользователи с постами:', JSON.stringify(users, null, 2));
  } catch (error) {
    console.error('Ошибка:', error);
  } finally {
    await prisma.$disconnect();
  }
})();

Благодаря Prisma, все операции полностью типизированы — вы получите ошибку на этапе компиляции, если попытаетесь передать неверное поле или тип.

3. Работа с MongoDB через Mongoose

MongoDB — это NoSQL база данных, которая хранит данные в формате, похожем на JSON. Mongoose предоставляет удобную типизацию для TypeScript.

3.1. Определение схем и типов

Создайте файл src/models/User.ts:

import mongoose, { Schema, Document, Model } from 'mongoose';

// Определение TypeScript интерфейса
export interface IUser extends Document {
  email: string;
  name?: string;
  age?: number;
  createdAt: Date;
  updatedAt: Date;
}

// Определение схемы
const UserSchema: Schema = new Schema(
  {
    email: {
      type: String,
      required: true,
      unique: true,
      lowercase: true,
      trim: true,
    },
    name: {
      type: String,
      trim: true,
    },
    age: {
      type: Number,
      min: 0,
    },
  },
  {
    timestamps: true, // автоматически добавляет createdAt и updatedAt
  }
);

// Экспорт модели с типизацией
export const User: Model<IUser> = mongoose.model<IUser>('User', UserSchema);

3.2. CRUD-операции с MongoDB

Создайте файл src/mongodb.ts:

import mongoose from 'mongoose';
import { User, IUser } from './models/User';

const MONGO_URI = 'mongodb://localhost:27017/ts_demo';

// Подключение к MongoDB
async function connectDB() {
  try {
    await mongoose.connect(MONGO_URI);
    console.log('Подключено к MongoDB');
  } catch (error) {
    console.error('Ошибка подключения:', error);
    process.exit(1);
  }
}

interface CreateUserInput {
  email: string;
  name?: string;
  age?: number;
}

// Создание пользователя
async function createUser(data: CreateUserInput): Promise<IUser> {
  const user = new User(data);
  return await user.save();
}

// Получение всех пользователей
async function getUsers(): Promise<IUser[]> {
  return await User.find().sort({ createdAt: -1 });
}

// Поиск пользователя по email
async function getUserByEmail(email: string): Promise<IUser | null> {
  return                

Блоги

Рекомендаций по книгам