如何实现TypeScript的convert函数根据KeysB类型条件返回不同值?
解决TypeScript中convert函数的类型判断与返回值问题
要实现根据输入值是否为KeysB类型返回不同结果的需求,核心问题在于TypeScript的泛型和条件类型是编译时概念,无法直接在运行时判断泛型参数的具体类型,需要结合运行时判断逻辑与类型守卫来让TS正确识别分支类型。
完整解决方案代码
type KeysA = 'itemA' | 'extraB'; type KeysB = 'A' | 'itemB'; // 定义运行时可访问的KeysB集合,用于判断输入值类型 const keysB: KeysB[] = ['A', 'itemB']; // 类型守卫函数:明确告知TS,返回true时输入值属于KeysB类型 function isKeysB(value: KeysA | KeysB): value is KeysB { return keysB.includes(value); } const convert = <E extends KeysA | KeysB>(value: E): E extends KeysB ? `key_${E}` : E => { if (isKeysB(value)) { // 当输入为KeysB时,返回拼接字符串,断言匹配条件类型分支 return `key_${value}` as E extends KeysB ? `key_${E}` : never; } else { // 输入为KeysA时返回原值,断言匹配条件类型分支 return value as E extends KeysA ? E : never; } } // 测试用例验证 const key1 = convert('itemA'); // 类型:'itemA',值:'itemA' const key2 = convert('extraB'); // 类型:'extraB',值:'extraB' const key3 = convert('A'); // 类型:'key_A',值:'key_A' const key4 = convert('itemB'); // 类型:'key_itemB',值:'key_itemB'
关键步骤说明
- 运行时类型判断基础:创建
keysB数组作为KeysB类型的运行时具象化集合,因为TS的类型信息在编译后会被擦除,无法直接在运行时用类型做判断。 - 类型守卫的作用:
isKeysB函数通过类型断言语法value is KeysB,让TypeScript能够在if分支中正确推断出value的具体类型,避免类型歧义。 - 返回值类型断言:由于TS无法自动将运行时的分支判断与编译时的条件类型完全对齐,需要用
as断言明确返回值符合条件类型的对应分支,消除类型错误。
简化版实现(无需单独类型守卫)
如果追求代码简洁,也可以直接在判断逻辑中使用类型断言:
type KeysA = 'itemA' | 'extraB'; type KeysB = 'A' | 'itemB'; const keysB: KeysB[] = ['A', 'itemB']; const convert = <E extends KeysA | KeysB>(value: E): E extends KeysB ? `key_${E}` : E => { if (keysB.includes(value as KeysB)) { return `key_${value}` as E extends KeysB ? `key_${E}` : never; } return value as E; }
内容的提问来源于stack exchange,提问作者Ewan
相关产品推荐
相关产品推荐

