1. lodash — Utility Library
npm install lodash
npm install -D @types/lodash
import _ from "lodash";
// pick / omit —— 提取或排除对象属性
const user = { id: 1, name: "Alice", password: "secret", role: "admin" };
const safe = _.omit(user, ["password"]); // { id, name, role }
const brief = _.pick(user, ["id", "name"]); // { id, name }
// debounce —— 防抖(常用于搜索输入)
const search = _.debounce((query: string) => {
console.log("搜索:", query);
}, 300);
// cloneDeep —— 深拷贝(比 structuredClone 兼容性更好)
const original = { a: { b: [1, 2, 3] } };
const copy = _.cloneDeep(original);
// groupBy —— 分组
const orders = [
{ product: "手机", category: "电子" },
{ product: "耳机", category: "电子" },
{ product: "T恤", category: "服装" },
];
const grouped = _.groupBy(orders, "category");
// { "电子": [...], "服装": [...] }
Tip: If only using a few functions, consider lodash-es with tree-shaking to reduce bundle size.
2. dayjs — Date Handling
dayjs is a lightweight replacement for moment.js (only 2KB), with an almost fully compatible API.
npm install dayjs
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import "dayjs/locale/zh-cn";
dayjs.extend(relativeTime);
dayjs.locale("zh-cn");
// 解析与格式化
const now = dayjs();
console.log(now.format("YYYY-MM-DD HH:mm:ss")); // "2026-03-30 14:30:00"
// 日期操作
const nextWeek = now.add(7, "day");
const lastMonth = now.subtract(1, "month");
// 相对时间(需要 relativeTime 插件)
console.log(dayjs("2026-03-28").fromNow()); // "2 天前"
// 比较
const deadline = dayjs("2026-04-15");
console.log(deadline.isAfter(now)); // true
console.log(deadline.diff(now, "day")); // 16
3. zod — Runtime Data Validation
zod validates data structures at runtime and automatically infers TypeScript types — define once, use twice.
npm install zod
import { z } from "zod";
// 定义 schema
const CreateUserSchema = z.object({
name: z.string().min(2).max(50),
email: z.string().email(),
age: z.number().int().min(0).max(150).optional(),
role: z.enum(["admin", "user", "guest"]).default("user"),
});
// 自动推导类型(无需手写 interface)
type CreateUserInput = z.infer<typeof CreateUserSchema>;
// 验证外部数据
function handleCreateUser(rawBody: unknown): CreateUserInput {
const result = CreateUserSchema.safeParse(rawBody);
if (!result.success) {
console.error("验证失败:", result.error.flatten());
throw new Error("Invalid input");
}
return result.data; // 类型安全的 CreateUserInput
}
4. winston / pino — Logging Libraries
Production environments need structured logging. winston is feature-rich, pino pursues extreme performance.
npm install winston
import winston from "winston";
const logger = winston.createLogger({
level: "info",
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(),
winston.format.simple()
),
}),
new winston.transports.File({ filename: "logs/error.log", level: "error" }),
new winston.transports.File({ filename: "logs/combined.log" }),
],
});
logger.info("服务已启动", { port: 3000 });
logger.error("数据库连接失败", { host: "localhost", error: "ECONNREFUSED" });
For high-performance scenarios, pino is recommended — JSON serialization is 5x+ faster than winston.
5. dotenv — Environment Variable Management
npm install dotenv
Create a .env file (add to .gitignore):
DATABASE_URL=postgresql://user:pass@localhost:5432/mydb
API_KEY=sk-xxxxxxxxxxxx
PORT=3000
import "dotenv/config"; // 在入口文件顶部导入
// 类型安全的环境变量读取
function getEnv(key: string): string {
const value = process.env[key];
if (!value) throw new Error(`缺少环境变量: ${key}`);
return value;
}
const dbUrl = getEnv("DATABASE_URL");
const port = Number(getEnv("PORT"));
6. vitest — Testing Framework
vitest is compatible with Jest API but faster, with native TypeScript and ESM support.
npm install -D vitest
// math.ts
export function add(a: number, b: number): number { return a + b; }
export function divide(a: number, b: number): number {
if (b === 0) throw new Error("除数不能为零");
return a / b;
}
// math.test.ts
import { describe, it, expect } from "vitest";
import { add, divide } from "./math";
describe("math 模块", () => {
it("add 正确相加", () => {
expect(add(2, 3)).toBe(5);
expect(add(-1, 1)).toBe(0);
});
it("divide 除零抛异常", () => {
expect(() => divide(10, 0)).toThrow("除数不能为零");
});
});
npx vitest # 监听模式
npx vitest run # 单次运行
npx vitest --coverage # 覆盖率报告
7. commander — CLI Tool Building
npm install commander
import { Command } from "commander";
const program = new Command();
program
.name("mytool")
.version("1.0.0")
.description("一个示例 CLI 工具");
program
.command("greet <name>")
.option("-l, --lang <language>", "语言", "zh")
.description("向某人打招呼")
.action((name: string, opts: { lang: string }) => {
const msg = opts.lang === "zh" ? `你好,${name}!` : `Hello, ${name}!`;
console.log(msg);
});
program.parse(); // 解析 process.argv
npx ts-node cli.ts greet Alice --lang en
# Hello, Alice!
8. Framework Selection Reference
Express
Most mature ecosystem with rich middleware. Suitable for rapid prototyping and small-to-medium projects.
Style: Minimal · Learning curve: Low
Fastify
High performance with built-in JSON Schema validation. 2-3x higher throughput than Express.
Style: Plugin-based · Learning curve: Medium
Koa
Built by the original Express team, based on async/await. More streamlined but smaller ecosystem than Express.
Style: Minimal · Learning curve: Low
NestJS
Enterprise framework with decorators + dependency injection. Heavily inspired by Angular and Spring Boot.
Style: Full-stack/Heavyweight · Learning curve: High
📝 Chapter Summary
lodash for data structures
omit/pick/groupBy/cloneDeep are high-frequency tools
dayjs replaces moment.js
2KB lightweight, compatible API, plugin extensions
zod = Validation + Type Inference
Define schema once, automatically get TypeScript types
vitest is the top choice for TS testing
Jest compatible, fast, native ESM support