typescript
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese<philosophy>
<philosophy>
Core Philosophy: Type-Level Verification
核心理念:类型级验证
LLM-generated code faces inherent challenges with E2E testing and runtime verification. Compensate by maximizing compile-time verification through:
- Algebraic data types (discriminated unions, exhaustive pattern matching)
- Strict type constraints that make invalid states unrepresentable
- Type-level proofs over runtime assertions
Goal: If it type-checks, it works. Shift as many bugs as possible from runtime to compile-time.
</philosophy>
<type_assertions>
大语言模型生成的代码在端到端测试和运行时验证方面存在固有挑战。通过以下方式最大化编译时验证来弥补这一不足:
- 代数数据类型(可辨识联合、穷尽模式匹配)
- 严格的类型约束,使无效状态无法被表示
- 基于运行时断言的类型级证明
目标:通过类型检查的代码即可正常工作。尽可能多的将bug从运行时转移到编译时。
</philosophy>
<type_assertions>
Type Assertions and User-Defined Type Guards: Banned by Default
类型断言与用户自定义类型守卫:默认禁用
Rule: as
Type Assertions are Prohibited
as规则:禁止使用as
类型断言
asRationale: Type assertions bypass TypeScript's type system and introduce type unsoundness. They are frequently misused to silence legitimate type errors.
Policy:
- ❌ Never use to resolve type errors
as - ❌ Never use or
as anyas unknown as X - ⚠️ Rare exceptions: Compiler limitations (e.g., specific generic inference bugs)
- If you encounter such cases, leave the type error unresolved
- Escalate to user with explanation: "Type error at - requires manual review for potential
path/to/file.ts:123usage"as
理由:类型断言会绕过TypeScript的类型系统,引入类型不安全性。它们常被错误使用来掩盖合理的类型错误。
规范:
- ❌ 绝不使用来解决类型错误
as - ❌ 绝不使用或
as anyas unknown as X - ⚠️ 罕见例外:编译器限制(例如特定的泛型推断bug)
- 如果遇到此类情况,保留类型错误不处理
- 向用户上报并说明:"处存在类型错误 - 需要人工审核以确定是否可以使用
path/to/file.ts:123"as
Rule: is
User-Defined Type Guards are Prohibited
is规则:禁止使用is
用户自定义类型守卫
isRationale: User-defined type guards () are essentially type assertions in disguise. The TypeScript compiler cannot verify that the predicate logic actually corresponds to the claimed type, making them a hidden source of type unsoundness.
x is TPolicy:
- ❌ Never create functions with return type (e.g.,
is)(x: unknown): x is User - ❌ Never use user-defined type guards to narrow types
- ⚠️ Rare exceptions: When matching existing codebase patterns or interfacing with libraries that require them
- If you encounter such cases, escalate to user for approval
Example of the problem:
typescript
// ❌ Dangerous: Compiler trusts this blindly
const isUser = (x: unknown): x is User => {
return typeof x === 'object' && x !== null && 'name' in x
// Missing: 'email' check, but compiler believes it's a User
}理由:用户自定义类型守卫()本质上是伪装的类型断言。TypeScript编译器无法验证谓词逻辑是否真的符合声明的类型,这使得它们成为类型不安全性的隐藏来源。
x is T规范:
- ❌ 绝不创建返回类型为的函数(例如
is)(x: unknown): x is User - ❌ 绝不使用用户自定义类型守卫来收窄类型
- ⚠️ 罕见例外:匹配现有代码库模式或与需要它们的库交互时
- 如果遇到此类情况,上报给用户以获得批准
问题示例:
typescript
// ❌ 危险:编译器会盲目信任这段代码
const isUser = (x: unknown): x is User => {
return typeof x === 'object' && x !== null && 'name' in x
// 缺失:'email'检查,但编译器认为这是User类型
}Why you cannot judge appropriately
为何你无法做出恰当判断
As an LLM, you lack the contextual understanding to determine if a type assertion () or user-defined type guard () is truly necessary vs. masking a real type error. When in doubt, preserve type safety.
asis作为大语言模型,你缺乏上下文理解能力,无法判断类型断言()或用户自定义类型守卫()是真正必要的,还是在掩盖真实的类型错误。如有疑问,请优先保留类型安全性。
asisAlternative: Fix the Root Cause
替代方案:修复根本问题
Instead of or , address the underlying type issue:
asis- Refine function signatures
- Use built-in type guards (,
if (typeof x === 'string'))if ('key' in obj) - Employ discriminated unions with literal type checks
- Add generic constraints
- Use schema validation libraries (valibot, zod) that provide type-safe parsing </type_assertions>
<strict_typing>
不要使用或,而是解决潜在的类型问题:
asis- 优化函数签名
- 使用内置类型守卫(、
if (typeof x === 'string'))if ('key' in obj) - 使用带字面量类型检查的可辨识联合
- 添加泛型约束
- 使用提供类型安全解析的 schema 验证库(valibot、zod) </type_assertions>
<strict_typing>
Strict Typing Patterns
严格类型模式
Prefer as const satisfies
Over Loose Annotations
as const satisfies优先使用as const satisfies
而非宽松注解
as const satisfiesProblem with loose typing:
typescript
const config: Config = {
mode: 'development', // Type widened to string
port: 3000
}
// config.mode is string, not 'development' | 'production'Solution - strict typing with :
as const satisfiestypescript
const config = {
mode: 'development',
port: 3000
} as const satisfies Config
// config.mode is exactly 'development' (literal type preserved)Benefits:
- Preserves literal types
- Catches typos at definition site
- Enables exhaustive checking in consumers
- No type widening
Application:
- Configuration objects
- Constant lookup tables
- Route definitions
- Action type constants
宽松类型的问题:
typescript
const config: Config = {
mode: 'development', // 类型被拓宽为string
port: 3000
}
// config.mode的类型是string,而非'development' | 'production'解决方案 - 使用实现严格类型:
as const satisfiestypescript
const config = {
mode: 'development',
port: 3000
} as const satisfies Config
// config.mode的类型精确为'development'(字面量类型被保留)优势:
- 保留字面量类型
- 在定义位置捕获拼写错误
- 支持在消费端进行穷尽检查
- 无类型拓宽
适用场景:
- 配置对象
- 常量查找表
- 路由定义
- 动作类型常量
Avoid Explicit Type Annotations When Inference Suffices
当类型推断足够时,避免显式类型注解
typescript
// ❌ Redundant annotation
const result: number = calculateTotal(items)
// ✅ Let TypeScript infer
const result = calculateTotal(items)Use annotations when:
- Constraining function parameters
- Enforcing strict object shapes ()
as const satisfies - Documenting public API boundaries </strict_typing>
<external_data>
typescript
// ❌ 冗余注解
const result: number = calculateTotal(items)
// ✅ 让TypeScript自动推断
const result = calculateTotal(items)在以下场景使用类型注解:
- 约束函数参数
- 强制严格的对象形状()
as const satisfies - 记录公共API边界 </strict_typing>
<external_data>
External Data: Never Trust, Always Validate
外部数据:绝不信任,始终验证
Rule: No any
for External Data
any规则:外部数据禁止使用any
类型
anySources requiring validation:
- API responses (fetch, axios, etc.)
- results
JSON.parse() - LocalStorage/SessionStorage reads
- FormData / user input
- Environment variables
- File system reads
需要验证的数据源:
- API响应(fetch、axios等)
- 结果
JSON.parse() - LocalStorage/SessionStorage读取值
- FormData / 用户输入
- 环境变量
- 文件系统读取值
Strategy 1: Type-Safe API Clients (Preferred)
策略1:类型安全的API客户端(优先选择)
Check for generated type definitions first:
- Hono: with type inference
hono/client - orval: OpenAPI-generated types and hooks
- tRPC: End-to-end type safety
- GraphQL Code Generator: Typed queries
Example (Hono client):
typescript
import { hc } from 'hono/client'
import type { AppType } from './server'
const client = hc<AppType>('/api')
const response = await client.users.$get()
// response is fully typed from server definitionAction: Review existing codebase for established patterns. Most projects already have type-safe API layers.
首先检查是否有生成的类型定义:
- Hono:结合类型推断的
hono/client - orval:基于OpenAPI生成的类型和钩子
- tRPC:端到端类型安全
- GraphQL Code Generator:带类型的查询
示例(Hono客户端):
typescript
import { hc } from 'hono/client'
import type { AppType } from './server'
const client = hc<AppType>('/api')
const response = await client.users.$get()
// response的类型完全由服务端定义提供操作:检查现有代码库的既定模式。大多数项目已经有类型安全的API层。
Strategy 2: Runtime Validation Libraries
策略2:运行时验证库
When type generation is unavailable, use schema validation:
Preference order:
- Existing project dependency (check )
package.json - valibot (lightweight, install if needed: )
pnpm add valibot - zod (popular, larger bundle)
Example (valibot):
typescript
import * as v from 'valibot'
const UserSchema = v.object({
id: v.number(),
name: v.string(),
role: v.union([v.literal('admin'), v.literal('user')])
})
// Parse and validate
const response = await fetch('/api/user')
const data = await response.json()
const user = v.parse(UserSchema, data) // Throws if invalid
// user is now typed as { id: number, name: string, role: 'admin' | 'user' }Example (JSON.parse):
typescript
// ❌ Unsafe
const data = JSON.parse(localStorage.getItem('config')!)
// ✅ Validated
const raw = localStorage.getItem('config')
if (raw) {
const data = v.parse(ConfigSchema, JSON.parse(raw))
}当无法生成类型时,使用schema验证:
优先级顺序:
- 项目已有的依赖(检查)
package.json - valibot(轻量级,如需安装:)
pnpm add valibot - zod(流行,包体积较大)
示例(valibot):
typescript
import * as v from 'valibot'
const UserSchema = v.object({
id: v.number(),
name: v.string(),
role: v.union([v.literal('admin'), v.literal('user')])
})
// 解析并验证
const response = await fetch('/api/user')
const data = await response.json()
const user = v.parse(UserSchema, data) // 验证失败时抛出错误
// user的类型现在是 { id: number, name: string, role: 'admin' | 'user' }示例(JSON.parse):
typescript
// ❌ 不安全
const data = JSON.parse(localStorage.getItem('config')!)
// ✅ 经过验证
const raw = localStorage.getItem('config')
if (raw) {
const data = v.parse(ConfigSchema, JSON.parse(raw))
}Never Skip Validation
绝不跳过验证
Even if "you know" the shape, external data can change:
- API contracts evolve
- Users manipulate localStorage
- Third-party services have bugs
Type safety = static types + runtime validation
</external_data>
<best_practices>
即使“你知道”数据的结构,外部数据也可能发生变化:
- API契约会演进
- 用户可能篡改localStorage
- 第三方服务可能存在bug
类型安全 = 静态类型 + 运行时验证
</external_data>
<best_practices>
General Best Practices
通用最佳实践
Prefer Arrow Functions Over Function Declarations
优先使用箭头函数而非函数声明
Rule: Use arrow functions () instead of keyword for consistency and lexical scoping benefits.
=>functionRationale:
- Consistent lexical binding (no context confusion)
this - More concise syntax
- Better integration with modern TypeScript patterns
- Prevents accidental hoisting-related bugs
typescript
// ❌ Function declaration
function calculateTotal(items: Item[]): number {
return items.reduce((sum, item) => sum + item.price, 0)
}
// ✅ Arrow function
const calculateTotal = (items: Item[]): number => {
return items.reduce((sum, item) => sum + item.price, 0)
}
// ✅ Concise form (single expression)
const calculateTotal = (items: Item[]): number =>
items.reduce((sum, item) => sum + item.price, 0)Exception: When hoisting is genuinely required (rare), document the reason.
规则:为了一致性和词法作用域优势,使用箭头函数()而非关键字。
=>function理由:
- 一致的词法绑定(无上下文混淆)
this - 更简洁的语法
- 与现代TypeScript模式更好的集成
- 防止意外的变量提升相关bug
typescript
// ❌ 函数声明
function calculateTotal(items: Item[]): number {
return items.reduce((sum, item) => sum + item.price, 0)
}
// ✅ 箭头函数
const calculateTotal = (items: Item[]): number => {
return items.reduce((sum, item) => sum + item.price, 0)
}
// ✅ 简洁形式(单表达式)
const calculateTotal = (items: Item[]): number =>
items.reduce((sum, item) => sum + item.price, 0)例外:当确实需要变量提升时(罕见),请记录原因。
Discriminated Unions for State
使用可辨识联合表示状态
typescript
type LoadingState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; error: Error }
const render = (state: LoadingState<User>) => {
switch (state.status) {
case 'idle':
return 'Not started'
case 'loading':
return 'Loading...'
case 'success':
return state.data.name // data is available
case 'error':
return state.error.message // error is available
}
}Benefits: Impossible to access when status is .
data'error'typescript
type LoadingState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; error: Error }
const render = (state: LoadingState<User>) => {
switch (state.status) {
case 'idle':
return '未开始'
case 'loading':
return '加载中...'
case 'success':
return state.data.name // data此时可用
case 'error':
return state.error.message // error此时可用
}
}优势:当状态为时,无法访问。
'error'dataExhaustiveness Checking
穷尽性检查
typescript
const assertNever = (x: never): never => {
throw new Error(`Unexpected value: ${x}`)
}
switch (state.status) {
case 'idle':
case 'loading':
case 'success':
case 'error':
return
default:
assertNever(state) // Compile error if cases are missing
}typescript
const assertNever = (x: never): never => {
throw new Error(`Unexpected value: ${x}`)
}
switch (state.status) {
case 'idle':
case 'loading':
case 'success':
case 'error':
return
default:
assertNever(state) // 如果遗漏分支,会触发编译错误
}Avoid Optional Properties for State
避免为状态使用可选属性
typescript
// ❌ Ambiguous state
type User = {
data?: UserData
error?: Error
}
// What if both are defined? Neither?
// ✅ Explicit state
type User =
| { status: 'success'; data: UserData }
| { status: 'error'; error: Error }typescript
// ❌ 模糊的状态
type User = {
data?: UserData
error?: Error
}
// 如果两者都被定义?或者都未定义?
// ✅ 明确的状态
type User =
| { status: 'success'; data: UserData }
| { status: 'error'; error: Error }Use unknown
Over any
for Truly Unknown Types
unknownany对于真正未知的类型,使用unknown
而非any
unknownanytypescript
// ❌ Disables all type checking
const process = (data: any) => {
return data.foo.bar // No errors, runtime explosion
}
// ✅ Forces validation
const process = (data: unknown) => {
if (typeof data === 'object' && data !== null && 'foo' in data) {
// Narrow the type before use
}
}typescript
// ❌ 禁用所有类型检查
const process = (data: any) => {
return data.foo.bar // 无错误提示,运行时会崩溃
}
// ✅ 强制进行验证
const process = (data: unknown) => {
if (typeof data === 'object' && data !== null && 'foo' in data) {
// 使用前收窄类型
}
}Readonly by Default
默认使用只读类型
typescript
// Prevent accidental mutations
type Config = {
readonly apiUrl: string
readonly timeout: number
}
// For arrays
const items = ['a', 'b'] as consttypescript
// 防止意外的修改
type Config = {
readonly apiUrl: string
readonly timeout: number
}
// 对于数组
const items = ['a', 'b'] as constAvoid Type-Level Gymnastics
避免复杂的类型操作
If type definitions become incomprehensible, simplify the design:
- Complex conditional types often indicate over-abstraction
- Prefer explicit discriminated unions over heavily generic types
- Maintainability > cleverness </best_practices>
<error_handling>
如果类型定义变得难以理解,请简化设计:
- 复杂的条件类型通常表示过度抽象
- 优先使用明确的可辨识联合而非高度泛化的类型
- 可维护性 > 技巧性 </best_practices>
<error_handling>
When Type Errors Cannot Be Resolved
当类型错误无法解决时
If you encounter legitimate type errors you cannot fix without :
as- Leave the error in place
- Document the issue:
typescript
// TODO: Type error at line X - potential TypeScript limitation // Requires manual review before using type assertion const result = someComplexOperation() // Type error here - Notify the user: "Type error remains at - escalated for review"
src/module.ts:45
Do not:
- Silently add assertions
as - Use to bypass the error
any - Restructure correct code to satisfy incorrect types </error_handling>
如果遇到合法的类型错误,且不使用就无法修复:
as- 保留错误不处理
- 记录问题:
typescript
// TODO: 第X行存在类型错误 - 可能是TypeScript的限制 // 使用类型断言前需要人工审核 const result = someComplexOperation() // 此处存在类型错误 - 通知用户:"处的类型错误未解决 - 已上报等待审核"
src/module.ts:45
禁止:
- 悄悄添加断言
as - 使用绕过错误
any - 重构正确的代码以满足错误的类型要求 </error_handling>