前后端共享类型契约
Monorepo 中前后端共享类型的设计:packages/contracts 包定义 API 契约,编译时发现不一致。
#type / concept
#status / growing
#tech / dev / frontend / eng
[!info] related notes
- 工程: Monorepo 工程组织
前后端共享类型契约
核心问题
前端定义 interface User { id: string; name: string },后端返回 { id: "123", username: "test" }——字段名不一致,运行时才发现。
解决方案
在 packages/contracts 中定义共享类型:
// packages/contracts/src/consultation.ts
export interface ConsultationSession {
id: string;
user_id: string;
messages: ConsultationMessage[];
status: 'in_progress' | 'completed';
phase: ConsultationPhase;
}
前端直接 import:
import type { ConsultationSession } from '@bodysense/contracts';
package.json
{
"name": "@bodysense/contracts",
"main": "./src/index.ts",
"types": "./src/index.ts"
}
直接指向源码,monorepo 内不需要编译。
与 Go 类型的对应
TypeScript contracts 和 Go struct 的 JSON tag 需要手动保持一致。更高级的方案可以用代码生成工具(如 openapi-generator)自动同步。
与 tRPC/OpenAPI 的对比
| 方案 | 复杂度 | 适用 |
|---|---|---|
| 手动 contracts | 低 | Go + React |
| tRPC | 中 | Node 全栈 |
| OpenAPI codegen | 高 | 任意语言 |
Go + React 的组合用 contracts 包最简单。