TypeScript bilan Node.js va Express — tiplar, middleware, generic

~25 daq · TypeScript · Modullar, Sozlash va Amaliy

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.