TypeScript bilan Node.js va Express — tiplar, middleware, generic
Express da TypeScript ishlatish — req.body, req.params, res.json() ni tipizatsiya qilish. Middleware da req.user kabi kengaytmalar. Bu kursning yakuniy darsi — barcha bilimlar birgalikda.
O'rnatish
npm install express
npm install --save-dev @types/express typescript ts-node
tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"strict": true,
"outDir": "dist",
"rootDir": "src"
}
}
Asosiy Express server
import express, { Request, Response, NextFunction } from "express";
const app = express();
app.use(express.json());
app.get("/", (req: Request, res: Response) => {
res.json({ xabar: "Salom!" });
});
app.listen(3000, () => console.log("Server: 3000"));
req.params va req.body tipizatsiyasi
interface FoydalanuvchiParams {
id: string; // params har doim string
}
interface FoydalanuvchiBody {
ism: string;
email: string;
}
app.get("/users/:id",
(req: Request<FoydalanuvchiParams>, res: Response) => {
const id = parseInt(req.params.id); // string → number
res.json({ id });
}
);
app.post("/users",
(req: Request<{}, {}, FoydalanuvchiBody>, res: Response) => {
const { ism, email } = req.body; // tipizatsiyalangan
res.status(201).json({ ism, email });
}
);
Request<Params, ResBody, ReqBody, Query> — to'liq generic Request turi.
req.user — module augmentation
// src/types/express.d.ts
export interface AuthUser {
id: number;
email: string;
rol: "user" | "admin";
}
declare global {
namespace Express {
interface Request {
user?: AuthUser;
}
}
}
Endi barcha route larda req.user TypeScript tomonidan taniladi.
Middleware tipizatsiyasi
import { Request, Response, NextFunction } from "express";
import { AuthUser } from "./types/express";
function authMiddleware(
req: Request,
res: Response,
next: NextFunction
): void {
const token = req.headers.authorization?.split(" ")[1];
if (!token) {
res.status(401).json({ xabar: "Token kerak" });
return;
}
// token tekshiruv...
req.user = { id: 1, email: "j@mail.com", rol: "user" };
next();
}
app.use(authMiddleware);
app.get("/profil", (req, res) => {
if (!req.user) return res.status(401).json({});
res.json({ id: req.user.id, email: req.user.email });
});
Generic controller pattern
import { Request, Response } from "express";
type AsyncHandler<P = {}, B = {}, Q = {}> = (
req: Request<P, {}, B, Q>,
res: Response
) => Promise<void>;
function asyncWrap<P, B, Q>(handler: AsyncHandler<P, B, Q>) {
return async (req: Request<P, {}, B, Q>, res: Response, next: NextFunction) => {
try {
await handler(req, res);
} catch (err) {
next(err);
}
};
}
// Ishlatish
app.get("/users/:id", asyncWrap<{ id: string }>(async (req, res) => {
const user = await topishId(parseInt(req.params.id));
if (!user) return res.status(404).json({ xabar: "Topilmadi" });
res.json(user);
}));
Xato middleware
import { Request, Response, NextFunction } from "express";
interface AppXato {
message: string;
status: number;
}
function xatoMiddleware(
err: AppXato | Error,
req: Request,
res: Response,
next: NextFunction
): void {
const status = "status" in err ? err.status : 500;
const message = err.message || "Server xatosi";
res.status(status).json({ xabar: message });
}
app.use(xatoMiddleware);
Xulosa
// O'rnatish
npm install express @types/express
// Request<Params, ResBody, ReqBody, Query>
app.get("/users/:id",
(req: Request<{ id: string }>, res: Response) => { ... }
);
// req.user kengaytirish
declare global {
namespace Express {
interface Request { user?: AuthUser; }
}
}
// Middleware
(req: Request, res: Response, next: NextFunction): void => { ... }
// Async wrapper — xatolarni next ga uzatish
function asyncWrap(fn: AsyncHandler) {
return (req, res, next) => fn(req, res).catch(next);
}
TypeScript bilan Express — tur xavfsiz, autocomplete to'liq, xatolar yozilayotganda ko'rinadi. Bu kursda o'rgangan barcha TypeScript tushunchalari — real loyihada shu tarzda birlashadi.