TypeScript 在 Node.js 中的实战应用

小飞兽 JavaScript 314 次阅读 2026-07-23

项目初始化

npm init -y
npm install -D typescript @types/node ts-node
npx tsc --init
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "CommonJS",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

Express + TypeScript 实战

import express, { Request, Response, NextFunction } from 'express';

const app = express();
app.use(express.json());

interface User {
id: number;
name: string;
email: string;
}

const users: User[] = [
{ id: 1, name: '张三', email: 'zhang@example.com' },
{ id: 2, name: '李四', email: 'li@example.com' },
];

app.get('/api/users', (req: Request, res: Response) => {
res.json(users);
});

app.get('/api/users/:id', (req: Request, res: Response) => {
const user = users.find(u => u.id === parseInt(req.params.id));
if (!user) return res.status(404).json({ error: '用户不存在' });
res.json(user);
});

app.post('/api/users', (req: Request, res: Response) => {
const { name, email } = req.body as Omit;
if (!name || !email) return res.status(400).json({ error: 'name 和 email 必填' });
const newUser: User = { id: users.length + 1, name, email };
users.push(newUser);
res.status(201).json(newUser);
});

app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
console.error(err.stack);
res.status(500).json({ error: '服务器内部错误' });
});

app.listen(3000, () => { console.log('服务运行在 http://localhost:3000'); });

export default app;


自定义类型中间件


import { Request, Response, NextFunction } from 'express';

declare global {
namespace Express {
interface Request {
user?: { id: number; role: string };
requestId?: string;
}
}
}

function auth(req: Request, res: Response, next: NextFunction) {
const token = req.headers.authorization;
if (!token) return res.status(401).json({ error: '未登录' });
try {
req.user = verifyToken(token);
next();
} catch {
res.status(401).json({ error: 'Token 无效' });
}
}

app.get('/api/protected', auth, (req: Request, res: Response) => {
res.json({ message: '受保护的资源', user: req.user });
});


数据库操作类型安全


interface QueryResult {
rows: T[];
rowCount: number;
}

async function query(sql: string, params: any[] = []): Promise {
const { rows } = await pool.query(sql, params);
return rows as T[];
}

interface UserRow {
id: number;
name: string;
created_at: Date;
}

async function getUsers(): Promise {
return query('SELECT id, name, created_at FROM users LIMIT 50');
}

async function getUserById(id: number): Promise {
const results = await query(
'SELECT id, name, created_at FROM users WHERE id = $1', [id]
);
return results[0] ?? null;
}


常用脚本配置


{
"scripts": {
"dev": "ts-node src/app.ts",
"build": "tsc",
"start": "node dist/app.js",
"typecheck": "tsc --noEmit"
}
}