TypeScript如何使用infer关键字实现值类型到字符串标识的反向类型查找
问题根源
TypeScript 无法为泛型参数下的链式条件类型自动建立和 ValueTypeMap 的映射关联,所以才会报类型不兼容的错误。
最优解决方案
以 ValueTypeMap 作为唯一的类型真值源,所有衍生类型和逻辑都基于它推导,天然支持双向查找,不需要手动维护条件类型。
完整实现代码
// 基础类型定义 type Color = { r: number; g: number; b: number; a: number }; type Position = { x: number; y: number }; // 唯一真值源:字符串标识和值类型的映射 type ValueTypeMap = { "color": Color; "number": number; "position": Position; }; // 直接从 ValueTypeMap 推导两个联合类型,不需要手动重复定义 type PossibleValueTypesAsString = keyof ValueTypeMap; type PossibleValueTypes = ValueTypeMap[PossibleValueTypesAsString]; // 原有生成值的函数保持不变,正常工作 function generateRandomValueOfType<T extends PossibleValueTypesAsString>(type: T) : ValueTypeMap[T] { if (type === 'color') { return { r: 1, g: 1, b: 1, a: 1 } as ValueTypeMap[T] } if (type === "position") { return { x:1, y: 1 } as ValueTypeMap[T] } if (type === "number") { return 1 as ValueTypeMap[T]; } throw new Error ("We shouldn't have got here"); };
1. 通用反向查找工具类型
如果需要单独根据值类型反查对应字符串标识类型,可以直接用这个通用工具,不需要写链式条件:
// 入参:映射类型、值类型;返回:对应的key类型 type ReverseLookup<Map, ValueType> = { [K in keyof Map]: Map[K] extends ValueType ? K : never }[keyof Map]; // 用例 type ColorKey = ReverseLookup<ValueTypeMap, Color>; // 自动推导为 "color" type NumberKey = ReverseLookup<ValueTypeMap, number>; // 自动推导为 "number"
2. 修复原报错函数
直接把泛型绑定到字符串标识类型,避免反向推导的类型失效问题:
function hasAValueAcceptingCallback<K extends PossibleValueTypesAsString>( callback: (value: ValueTypeMap[K]) => void, valueTypeAsString: K ) { const value = generateRandomValueOfType(valueTypeAsString); callback(value); // 无任何类型错误 } // 调用验证 hasAValueAcceptingCallback((v: Position) => console.log(v.x), "position"); // 正常执行 hasAValueAcceptingCallback((v: number) => console.log(v), "position"); // 符合预期报错
方案优势
- 所有类型定义只有一份真值源,新增类型只需要在
ValueTypeMap里加一条即可,不需要手动修改联合类型和条件类型 - 没有冗余的链式条件类型,类型推导更稳定,不会出现泛型下的类型关联失效问题
- 双向查找都直接基于
ValueTypeMap完成,逻辑完全一致
内容的提问来源于stack exchange,提问作者dwjohnston
相关产品推荐
相关产品推荐

