您现在的位置是:网站首页 > TypeScript支持与开发实践文章详情

TypeScript支持与开发实践

TypeScript与Express框架的集成基础

Express作为Node.js最流行的Web框架之一,与TypeScript的结合能显著提升开发体验。通过@types/express类型定义包,我们可以获得完整的类型提示:

npm install express @types/express typescript --save-dev

基础类型化应用示例:

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

const app = express();
const port: number = 3000;

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

app.get('/users/:id', (req: Request<{ id: string }>, res: Response<User>) => {
  const userId = parseInt(req.params.id);
  // 类型系统会检查返回对象是否符合User结构
  res.json({ id: userId, name: 'TypeScript User' });
});

app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

中间件的类型安全实现

Express中间件在TypeScript中可以获得完整的类型支持。自定义中间件需要遵循RequestHandler类型:

import { RequestHandler } from 'express';

const loggerMiddleware: RequestHandler = (req, res, next) => {
  console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`);
  next();
};

const validateUser: RequestHandler<{}, {}, { username: string }> = (req, res, next) => {
  if (!req.body.username || req.body.username.length < 3) {
    return res.status(400).json({ error: 'Invalid username' });
  }
  next();
};

app.use(express.json());
app.use(loggerMiddleware);
app.post('/register', validateUser, (req, res) => {
  // req.body.username在这里已经被类型检查
});

路由控制的类型化组织

通过TypeScript的模块系统可以更好地组织路由:

// routes/users.ts
import { Router } from 'express';
import { UserService } from '../services/user';

const router = Router();
const userService = new UserService();

router.get('/', async (req, res) => {
  const users = await userService.getAll();
  res.json(users);
});

router.post('/', async (req, res) => {
  const newUser = await userService.create(req.body);
  res.status(201).json(newUser);
});

export default router;

然后在主应用中:

// app.ts
import userRouter from './routes/users';

app.use('/api/users', userRouter);

错误处理的类型安全模式

构建类型化的错误处理中间件:

class AppError extends Error {
  constructor(
    public statusCode: number,
    public message: string,
    public isOperational = true
  ) {
    super(message);
  }
}

const errorHandler: ErrorRequestHandler = (err: AppError, req, res, next) => {
  res.status(err.statusCode || 500).json({
    status: 'error',
    message: err.message,
    stack: process.env.NODE_ENV === 'development' ? err.stack : undefined
  });
};

app.get('/error', () => {
  throw new AppError(400, 'This is a typed error');
});

app.use(errorHandler);

数据库集成的类型实践

使用TypeORM进行类型安全的数据库操作:

import { Entity, PrimaryGeneratedColumn, Column, createConnection } from 'typeorm';

@Entity()
class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column()
  email: string;
}

const initializeDB = async () => {
  const connection = await createConnection({
    type: 'postgres',
    host: 'localhost',
    port: 5432,
    username: 'test',
    password: 'test',
    database: 'test',
    entities: [User],
    synchronize: true
  });

  const userRepo = connection.getRepository(User);
  const newUser = userRepo.create({ name: 'TS User', email: 'ts@example.com' });
  await userRepo.save(newUser);
};

配置管理的类型安全方案

使用dotenv配合类型检查:

import * as dotenv from 'dotenv';
import { z } from 'zod';

dotenv.config();

const envSchema = z.object({
  PORT: z.string().transform(Number),
  DB_HOST: z.string(),
  DB_PORT: z.string().transform(Number),
  NODE_ENV: z.enum(['development', 'production', 'test'])
});

const env = envSchema.parse(process.env);

const config = {
  port: env.PORT,
  db: {
    host: env.DB_HOST,
    port: env.DB_PORT
  },
  isDev: env.NODE_ENV === 'development'
};

测试策略的类型化实现

使用Jest进行类型安全的测试:

import request from 'supertest';
import app from '../app';

describe('User API', () => {
  it('GET /users should return array of users', async () => {
    const res = await request(app)
      .get('/api/users')
      .expect(200);
    
    // 类型断言
    const users: Array<{ id: number; name: string }> = res.body;
    expect(users.length).toBeGreaterThan(0);
  });

  it('POST /users requires valid email', async () => {
    await request(app)
      .post('/api/users')
      .send({ name: 'Test', email: 'invalid' })
      .expect(400);
  });
});

性能优化的类型安全方法

使用@types/benchmark进行类型化的性能测试:

import Benchmark from 'benchmark';
import { UserService } from '../services/user';

const suite = new Benchmark.Suite();
const userService = new UserService();

suite
  .add('Array#filter', async () => {
    await userService.getActiveUsersFilter();
  })
  .add('Database query', async () => {
    await userService.getActiveUsersQuery();
  })
  .on('cycle', (event: Benchmark.Event) => {
    console.log(String(event.target));
  })
  .run({ async: true });

部署流程的类型检查

创建类型化的部署配置:

interface DeploymentConfig {
  target: 'production' | 'staging';
  region: string;
  memorySize: number;
  timeout: number;
  environment: Record<string, string>;
}

const config: DeploymentConfig = {
  target: 'production',
  region: 'us-east-1',
  memorySize: 1024,
  timeout: 30,
  environment: {
    NODE_ENV: 'production',
    DB_URL: process.env.PROD_DB_URL!
  }
};

const validateConfig = (config: DeploymentConfig) => {
  if (!config.environment.DB_URL) {
    throw new Error('Database URL is required');
  }
};

高级类型技巧在Express中的应用

使用条件类型处理动态路由:

type RouteParams<T> = T extends `${string}:${infer Param}/${infer Rest}`
  ? { [K in Param | keyof RouteParams<Rest>]: string }
  : T extends `${string}:${infer Param}`
  ? { [K in Param]: string }
  : {};

function typedRoute<T extends string>(
  path: T,
  handler: (req: Request<RouteParams<T>>, res: Response) => void
) {
  app.get(path, handler);
}

typedRoute('/users/:userId/posts/:postId', (req, res) => {
  // req.params自动推断为 { userId: string; postId: string }
  const { userId, postId } = req.params;
});

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步