TypeScript Node 工程化实践

Node.js + TypeScript 工程化最佳实践:类型安全、装饰器模式、Clean Architecture、模块系统、构建配置与 Docker 多阶段构建。

1. TypeScript 类型系统

1.1 关键类型工具

// 接口与类型别名
interface User {
    id: string;
    name: string;
    email: string;
    role: 'admin' | 'user' | 'guest';
}

type UserInput = Omit<User, 'id'>;
type UserUpdate = Partial<User>;
type UserResponse = Pick<User, 'id' | 'name'>;

// 泛型函数
async function fetchApi<T>(url: string): Promise<T> {
    const res = await fetch(url);
    return res.json() as Promise<T>;
}

const user = await fetchApi<User>('/api/users/1');

// 条件类型
type IsString<T> = T extends string ? true : false;
type A = IsString<'hello'>;  // true
type B = IsString<123>;      // false

// 映射类型
type ReadonlyUser = { readonly [K in keyof User]: User[K] };

1.2 严格模式配置

{
    "compilerOptions": {
        "target": "ES2022",
        "module": "NodeNext",
        "moduleResolution": "NodeNext",
        "strict": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true,
        "resolveJsonModule": true,
        "declaration": true,
        "declarationMap": true,
        "sourceMap": true,
        "outDir": "./dist",
        "rootDir": "./src"
    },
    "include": ["src/**/*"],
    "exclude": ["node_modules", "dist"]
}

2. Clean Architecture

src/
├── domain/              # 核心业务逻辑(不依赖外部)
│   ├── entities/        # 实体
│   └── repositories/    # 仓库接口
│
├── application/         # 应用层
│   ├── services/        # 业务服务
│   └── dto/             # 数据传输对象
│
├── infrastructure/       # 基础设施
│   ├── db/              # 数据库实现
│   ├── http/            # 路由/控制器
│   └── cache/           # 缓存实现
│
└── main.ts              # 入口,组装依赖
// domain/repositories/user.repository.interface.ts
export interface IUserRepository {
    findById(id: string): Promise<User | null>;
    save(user: User): Promise<void>;
}

// infrastructure/db/prisma-user.repository.ts
export class PrismaUserRepository implements IUserRepository {
    constructor(private prisma: PrismaClient) {}
    
    async findById(id: string): Promise<User | null> {
        const user = await this.prisma.user.findUnique({ where: { id } });
        return user ? new User(user) : null;
    }
    
    async save(user: User): Promise<void> {
        await this.prisma.user.upsert({
            where: { id: user.id },
            update: user.toPrisma(),
            create: user.toPrisma()
        });
    }
}

3. Docker 多阶段构建

# 构建阶段
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json tsconfig.json ./
RUN npm ci
COPY src ./src
RUN npm run build

# 生产阶段
FROM node:20-alpine AS production
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
COPY --from=builder /app/dist ./dist
USER node
EXPOSE 3000
CMD ["node", "dist/main.js"]

延伸阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「nodejs」更多文章

  1. Node.js ORM 深度对比:Prisma、TypeORM、Sequelize 与 Drizzle
  2. Node.js 设计模式与最佳实践:从 SOLID 到六边形架构
  3. Node.js 高级测试策略:从单元测试到混沌工程的完整实践