如何基于联合类型标签实现类型安全的函数特化?
解决方案与案例
首先明确:不需要泛型化Item本身,利用TypeScript的分布式类型推断和映射类型关联,就能实现无需手动判断、无需外部传入slot的类型安全函数。下面结合代码示例说明:
基础类型定义
先还原你提到的核心类型:
type Item = 'Sword' | 'Shield' | 'Potion'; type ItemSlot = 'Weapon' | 'Armor' | 'Consumable'; // Item到对应Slot的映射类型 type ItemSlots = { Sword: 'Weapon'; Shield: 'Armor'; Potion: 'Consumable'; };
优化方案:自动推导Slot的类型安全函数
通过泛型函数+运行时映射表,让编译器自动从Item推导对应slot类型,无需手动传参或分支判断:
// 运行时映射表,同时保证类型对齐 const itemToSlot: Record<Item, ItemSlot> = { Sword: 'Weapon', Shield: 'Armor', Potion: 'Consumable' }; // 核心函数:泛型自动推导对应Slot类型 function putItem3<T extends Item>(item: T) { // 自动推断slot类型为ItemSlots[T],类型完全安全 const slot: ItemSlots[T] = itemToSlot[item]; // 后续逻辑可基于slot的具体类型做类型安全操作 if (slot === 'Weapon') { // 此处item必然是'Sword',类型自动收窄 console.log(`装备武器:${item}`); } } putItem3('Sword'); // 正常执行,slot类型为'Weapon' putItem3('Shield'); // slot类型自动推导为'Armor'
如果需要更细粒度的逻辑分支,还可以结合函数重载实现更精准的类型约束:
// 重载签名:明确每个Item对应的逻辑返回/约束 function putItem4(item: 'Sword'): void; function putItem4(item: 'Shield'): void; function putItem4(item: 'Potion'): void; // 实现体:复用映射表+类型收窄 function putItem4(item: Item) { const slot = itemToSlot[item]; switch (slot) { case 'Weapon': // 此处item类型自动收窄为'Sword' console.log(`强化武器:${item}`); break; case 'Armor': console.log(`装备护甲:${item}`); break; case 'Consumable': console.log(`使用药水:${item}`); break; } }
联合类型泛型处理实际案例
案例1:API响应通用转换器
针对不同类型的API响应,自动转换为前端业务模型:
// 联合类型的原始API响应 type ApiResponse = | { type: 'user', data: { id: number, name: string } } | { type: 'post', data: { id: number, title: string } } | { type: 'comment', data: { id: number, content: string } }; // 转换后的业务类型映射 type TransformedData = { user: { userId: number, userName: string }; post: { postId: number, postTitle: string }; comment: { commentId: number, commentContent: string }; }; // 泛型转换函数:自动推导响应类型并返回对应业务模型 function transformResponse<T extends ApiResponse>(res: T): TransformedData[T['type']] { switch (res.type) { case 'user': return { userId: res.data.id, userName: res.data.name } as any; case 'post': return { postId: res.data.id, postTitle: res.data.title } as any; case 'comment': return { commentId: res.data.id, commentContent: res.data.content } as any; } } // 使用示例:自动推导返回类型 const userData = transformResponse({ type: 'user', data: { id: 1, name: 'Alice' } }); // userData类型自动为{ userId: number, userName: string }
案例2:表单字段通用验证器
验证不同类型的表单字段,保证类型与验证逻辑对齐:
// 联合类型的表单字段 type FormField = | { type: 'text', value: string, minLength: number } | { type: 'number', value: number, min: number, max: number } | { type: 'checkbox', value: boolean }; // 泛型验证函数:针对不同字段类型执行对应逻辑 function validateField<T extends FormField>(field: T): { valid: boolean, message?: string } { switch (field.type) { case 'text': return field.value.length >= field.minLength ? { valid: true } : { valid: false, message: `最少需要${field.minLength}个字符` }; case 'number': return field.value >= field.min && field.value <= field.max ? { valid: true } : { valid: false, message: `数值必须在${field.min}~${field.max}之间` }; case 'checkbox': return { valid: field.value }; } } // 使用示例:自动适配字段类型 const textValid = validateField({ type: 'text', value: 'abc', minLength: 2 }); // textValid类型为{ valid: boolean, message?: string },逻辑对应文本字段验证
内容的提问来源于stack exchange,提问作者pickle
相关产品推荐
相关产品推荐

