Trigger Scenarios
- Refactoring table column definitions (dataIndex, columns)
- Refactoring enum type mappings (typeMap, statusMap)
- Refactoring data conversion logic (render functions, formatter)
- Multiple similar fields in the type definition (changedAt vs createdAt)
Core Principles
Do not infer field names from type definitions; you must look at the actual usage in the original code
Checklist
1. Field Name Verification
- Check the dataIndex in the original code
- Check the actual field names returned by the backend API
- Prefer required fields and avoid optional fields
- Pay attention to subtle differences in field names (changedAt vs createdAt, changeType vs operationType)
2. Enum Mapping Verification
- Check enum values one by one against the original code
- Ensure the mapping is complete (do not omit any enum value)
- Check the spelling of enum values (UPLOAD vs Upload)
- Check whether the colors and text of enum values are consistent
3. Runtime Testing
- TypeScript type checking passes (necessary but not sufficient)
- Test the functionality in the actual environment
- Check whether "Invalid Date", "undefined", or blank is displayed
- Check whether all enum values have corresponding mappings
Common Pitfalls
Pitfall 1: Ambiguous type definitions
Scenario: There are multiple similar fields in the type definition
interface InvoiceHistory {
changedAt?: string // 可选字段
createdAt: string // 必填字段
changeType?: string // 错误字段
operationType: string // 正确字段
}
Incorrect Approach:
// ❌ 根据类型定义推测,选择了可选字段
dataIndex: 'changedAt' // 可能为 undefined → Invalid Date
dataIndex: 'changeType' // 字段不存在 → 显示为空
Correct Approach:
// ✅ 查看原始代码的实际使用
git show HEAD~1:src/components/InvoiceHistoryTab.tsx
// 原始代码使用 createdAt(必填)和 operationType(正确)
dataIndex: 'createdAt'
dataIndex: 'operationType'
Pitfall 2: Incomplete enum mapping
Scenario: Some enum values are omitted during refactoring
Incorrect Approach:
// ❌ 只保留了 3 个类型
typeMap: {
CREATE: { text: '创建', color: 'green' },
UPDATE: { text: '更新', color: 'blue' },
DELETE: { text: '删除', color: 'red' },
}
Correct Approach:
// ✅ 查看原始代码,确保完整
git show HEAD~1:src/components/InvoiceHistoryTab.tsx
// 原始代码有 10 个类型
typeMap: {
UPLOAD: { text: '上传发票', color: 'blue' },
OCR_START: { text: '开始OCR', color: 'cyan' },
OCR_SUCCESS: { text: 'OCR成功', color: 'green' },
OCR_FAILED: { text: 'OCR失败', color: 'red' },
OCR_RETRY: { text: '重试OCR', color: 'orange' },
MANUAL_EDIT: { text: '手动编辑', color: 'orange' },
LINK_ORDER: { text: '关联订单', color: 'purple' },
UNLINK_ORDER: { text: '取消关联', color: 'magenta' },
FIELD_CONFIRM: { text: '确认字段', color: 'green' },
DELETE: { text: '删除发票', color: 'red' },
}
Pitfall 3: TypeScript cannot detect it
Scenario: The field name is wrong but TypeScript does not report an error
// ❌ TypeScript 不会报错(changedAt 在类型定义中存在)
dataIndex: 'changedAt' // 类型检查通过
render: (val: string) => new Date(val).toLocaleString()
// 运行时:val 为 undefined → Invalid Date
Correct Approach:
// ✅ 运行时测试 + 防御性编程
dataIndex: 'createdAt'
render: (val: string) => {
if (!val) return '-'
try {
return new Date(val).toLocaleString('zh-CN')
} catch {
return val
}
}
Pitfall 4: rowKey uses an optional field
Scenario: rowKey uses a field that may be undefined
Incorrect Approach:
// ❌ changedAt 可能为 undefined
rowKey={(record, index) => `${record.changedAt}-${index}`}
// 结果:undefined-0, undefined-1 → key 重复
Correct Approach:
// ✅ 使用必填字段 id
rowKey={(record) => record.id}
Verification Process
1. Static Checks
# TypeScript 类型检查
npm run type-check
# ESLint 检查
npm run lint
2. Runtime Testing
- Test the functionality in the development environment
- Check whether "Invalid Date" is displayed
- Check whether "undefined" or blank is displayed
- Check whether all enum values have corresponding mappings
- Check whether rowKey is unique
3. Comparative Verification
# 查看原始代码
git show HEAD~1:src/components/InvoiceHistoryTab.tsx
# 制作对比清单
| 字段 | 原始代码 | 重构后 | 状态 |
|------|---------|--------|------|
| 时间字段 | createdAt | changedAt | ❌ 错误 |
| 操作类型 | operationType | changeType | ❌ 错误 |
| 枚举映射 | 10 个 | 3 个 | ❌ 不完整 |
| rowKey | record.id | record.changedAt | ❌ 错误 |
Defensive Programming
1. Handling Optional Fields
// ✅ 检查字段是否存在
render: (val: string) => {
if (!val) return '-'
return val
}
2. Date Formatting
// ✅ 捕获异常
render: (val: string) => {
if (!val) return '-'
try {
return new Date(val).toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
})
} catch {
return val
}
}
3. Enum Mapping
// ✅ 提供默认值
render: (type: string) => {
const config = typeMap[type] || { text: type, color: 'default' }
return <Tag color={config.color}>{config.text}</Tag>
}
Rule Traceability
> 📋 本回复遵循:`field-mapping-safety` - [章节]