Как написать REST API на TypeScript за 30 минут: пошаговое руководство
Создание REST API — это базовая задача для любого backend-разработчика. Использование TypeScript добавляет строгую типизацию, улучшает читаемость кода и снижает количество ошибок. В этой статье мы разберем, как написать полноценный REST API на TypeScript с нуля всего за 30 минут. Вы познакомитесь с Express, TypeORM и лучшими практиками организации кода.
1. Настройка проекта и установка зависимостей
Первым делом создайте новую директорию и инициализируйте проект Node.js:
mkdir my-rest-api
cd my-rest-api
npm init -y
Установите необходимые пакеты:
npm install express reflect-metadata typeorm sqlite3
npm install -D typescript @types/node @types/express ts-node nodemon
Создайте файл tsconfig.json для конфигурации TypeScript:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}
2. Создание базовой структуры и точки входа
Организуйте структуру папок следующим образом:
src/— основной кодsrc/controllers/— контроллерыsrc/entities/— сущности базы данныхsrc/routes/— маршруты
Создайте файл src/index.ts — точку входа в приложение:
import "reflect-metadata";
import express from "express";
import { AppDataSource } from "./data-source";
import { userRoutes } from "./routes/userRoutes";
const app = express();
const PORT = process.env.PORT || 3000;
app.use(express.json());
AppDataSource.initialize()
.then(() => {
console.log("Database connected");
app.use("/api/users", userRoutes);
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
})
.catch((error) => console.log(error));
Теперь создайте src/data-source.ts для конфигурации TypeORM:
import { DataSource } from "typeorm";
import { User } from "./entities/User";
export const AppDataSource = new DataSource({
type: "sqlite",
database: "database.sqlite",
synchronize: true,
logging: false,
entities: [User],
});
3. Определение сущности и контроллера
Создайте файл src/entities/User.ts — модель пользователя:
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id!: number;
@Column()
name!: string;
@Column()
email!: string;
@Column({ default: true })
isActive!: boolean;
}
Теперь создадим контроллер src/controllers/userController.ts:
import { Request, Response } from "express";
import { AppDataSource } from "../data-source";
import { User } from "../entities/User";
const userRepository = AppDataSource.getRepository(User);
export const getUsers = async (req: Request, res: Response) => {
try {
const users = await userRepository.find();
res.json(users);
} catch (error) {
res.status(500).json({ message: "Error fetching users" });
}
};
export const getUserById = async (req: Request, res: Response) => {
try {
const user = await userRepository.findOneBy({ id: parseInt(req.params.id) });
if (!user) {
return res.status(404).json({ message: "User not found" });
}
res.json(user);
} catch (error) {
res.status(500).json({ message: "Error fetching user" });
}
};
export const createUser = async (req: Request, res: Response) => {
try {
const { name, email } = req.body;
const user = userRepository.create({ name, email });
const savedUser = await userRepository.save(user);
res.status(201).json(savedUser);
} catch (error) {
res.status(400).json({ message: "Error creating user" });
}
};
export const updateUser = async (req: Request, res: Response) => {
try {
const user = await userRepository.findOneBy({ id: parseInt(req.params.id) });
if (!user) {
return res.status(404).json({ message: "User not found" });
}
userRepository.merge(user, req.body);
const updatedUser = await userRepository.save(user);
res.json(updatedUser);
} catch (error) {
res.status(400).json({ message: "Error updating user" });
}
};
export const deleteUser = async (req: Request, res: Response) => {
try {
const result = await userRepository.delete(req.params.id);
if (result.affected === 0) {
return res.status(404).json({ message: "User not found" });
}
res.json({ message: "User deleted successfully" });
} catch (error) {
res.status(500).json({ message: "Error deleting user" });
}
};
4. Настройка маршрутов и запуск сервера
Создайте src/routes/userRoutes.ts:
import { Router } from "express";
import {
getUsers,
getUserById,
createUser,
updateUser,
deleteUser,
} from "../controllers/userController";
const router = Router();
router.get("/", getUsers);
router.get("/:id", getUserById);
router.post("/", createUser);
router.put("/:id", updateUser);
router.delete("/:id", deleteUser);
export { router as userRoutes };
Добавьте скрипты в package.json:
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "nodemon --exec ts-node src/index.ts"
}
Запустите сервер командой:
npm run dev
Теперь ваш REST API работает! Протестируйте его с помощью curl или Postman:
# Создать пользователя
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"name": "Иван", "email": "ivan@example.com"}'
# Получить всех пользователей
curl http://localhost:3000/api/users
Заключение
За 30 минут вы создали полноценный REST API на TypeScript с использованием Express и TypeORM. Ваше приложение поддерживает CRUD-операции, использует SQLite для хранения данных и имеет четкую архитектуру, разделяющую контроллеры, маршруты