clean-typescript-boundaries
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseClean Boundaries
清晰的边界处理
Boundary code converts uncertain external behavior into explicit internal contracts. Keep unsafe shapes at the edge and pass typed values inward.
边界代码将不确定的外部行为转换为明确的内部契约。将不安全的数据格式隔离在边缘,向内传递类型化的值。
B1: Validate At The Edge
B1: 在边界处验证
External data is until validated. Parse and normalize once, then use domain types internally.
unknownts
// Bad - assertion lets invalid data into the system
const user = JSON.parse(responseText) as User;
// Good - boundary handles parsing, validation, and source context
const user = parseUserResponse(responseText);
function parseUserResponse(responseText: string): User {
const payload = parseJson(responseText, "user response");
return parseUser(payload);
}Boundary parsers should reject invalid JSON, reject invalid shape, fill intentional defaults, and name the external source in errors.
外部数据在验证前属于类型。仅解析和标准化一次,之后在内部使用领域类型。
unknownts
// Bad - assertion lets invalid data into the system
const user = JSON.parse(responseText) as User;
// Good - boundary handles parsing, validation, and source context
const user = parseUserResponse(responseText);
function parseUserResponse(responseText: string): User {
const payload = parseJson(responseText, "user response");
return parseUser(payload);
}边界解析器应拒绝无效JSON、拒绝无效格式、填充预设默认值,并在错误信息中注明外部数据源。
B2: Make Configuration Typed
B2: 让配置类型化
Read environment variables, feature flags, and storage values once at startup or module boundaries. Convert strings into typed config before the rest of the app uses them.
在启动时或模块边界处一次性读取环境变量、功能标志和存储值。在应用其他部分使用之前,将字符串转换为类型化配置。
B3: Do Not Leak Vendor Types
B3: 避免暴露厂商类型
Wrap awkward SDKs and generated clients behind small adapters when their types or behavior should not shape the whole app.
ts
type PaymentReceipt = {
id: string;
totalCents: number;
};
interface Payments {
charge(request: ChargeRequest): Promise<PaymentReceipt>;
}Keep vendor-specific fields in the adapter unless the domain truly needs them.
当SDK或生成客户端的类型或行为不应影响整个应用时,用小型适配器封装这些难用的SDK和生成客户端。
ts
type PaymentReceipt = {
id: string;
totalCents: number;
};
interface Payments {
charge(request: ChargeRequest): Promise<PaymentReceipt>;
}除非领域确实需要,否则将厂商特定字段保留在适配器中。
B4: Boundary Tests
B4: 边界测试
Use focused tests around boundaries that are easy to misunderstand:
- Parser rejects invalid external shapes.
- Adapter maps SDK responses into domain types.
- Missing config fails with a useful message.
- Browser/storage fallbacks behave consistently.
针对容易被误解的边界进行针对性测试:
- 解析器拒绝无效的外部数据格式。
- 适配器将SDK响应映射为领域类型。
- 缺失配置时返回有用的错误信息。
- 浏览器/存储的回退行为一致。
Common Mistakes
常见错误
- Letting from a client library spread through application code.
any - Repeating JSON shape checks in many call sites.
- Treating generated API models as domain models by default.
- Hiding unsafe parsing behind helper names like without validation.
getUser()
- 让客户端库的类型扩散到应用代码中。
any - 在多个调用点重复检查JSON格式。
- 默认将生成的API模型当作领域模型使用。
- 在没有验证的情况下,将不安全的解析隐藏在这类辅助函数背后。
getUser()