TypeScript 在 Node.js 中的实战应用
项目初始化
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"
}
}