TypeScript中如何定义泛型变量实现多接口兼容键值对,避免使用any?
实现方案
你之前的写法存在两个核心问题:
- 普通对象
keyValuePair不支持keyValuePair<T>[keyId]这种直接附加泛型参数的语法 - TypeScript静态阶段无法感知你传入的泛型
T和keyId对应值的类型关系,需要通过合理的类型约束和校验来保证安全。
下面提供三种从简单到严谨的实现方案,全程不需要用到any类型:
方案1:泛型约束 + 类型断言(最简实现)
适合你能百分百保证业务中keyId对应的值类型和传入的泛型一致的场景:
// 约束泛型T只能是A或B,避免传入非法类型 export async function getKeyValuePair<T extends A | B>(keyId: string): Promise<T> { const value = keyValuePair[keyId]; if (value) { // 手动告知TS该值的类型为T,你需要自行保证业务层面类型匹配 return value as T; } // 处理无值场景,避免返回undefined不符合Promise<T>的类型约定,也可以根据业务调整为返回Promise<T | undefined> throw new Error(`key ${keyId} not found`); } // 调用示例 const aValue = await getKeyValuePair<A>('keyA'); // 自动推断aValue为A类型 const bValue = await getKeyValuePair<B>('keyB'); // 自动推断bValue为B类型
方案2:类型守卫实现运行时校验(类型安全升级)
增加运行时类型校验,避免断言带来的类型假象,编译和运行阶段都能保证类型正确:
// 类型守卫:判断值是否为A类型 function isA(value: A | B): value is A { return 'propertyA' in value; } // 类型守卫:判断值是否为B类型 function isB(value: A | B): value is B { return 'propertyF' in value; } export async function getKeyValuePair<T extends A | B>(keyId: string, validateType: (val: A|B) => val is T): Promise<T> { const value = keyValuePair[keyId]; if (!value) { throw new Error(`key ${keyId} not found`); } if (validateType(value)) { return value; } throw new Error(`key ${keyId} value type mismatch`); } // 调用示例,无需手动传泛型,TS自动推断返回类型 const aValue = await getKeyValuePair('keyA', isA); // 自动推断为A类型 const bValue = await getKeyValuePair('keyB', isB); // 自动推断为B类型
方案3:映射类型实现全自动类型推断(最优场景)
如果你的key和对应值的类型是固定映射关系(比如keyA一定对应A类型,keyB一定对应B类型),可以用映射类型实现零手动输入、编译阶段全校验的类型安全方案:
// 定义key到类型的映射关系 interface KeyTypeMap { keyA: A; keyB: B; // 后续新增key和对应类型直接在这里扩展即可 } // 调整keyValuePair的类型,约束每个key对应的值类型 const keyValuePair: { [K in keyof KeyTypeMap]?: KeyTypeMap[K] } = {}; // 函数泛型绑定key的类型,自动推断返回值类型 export async function getKeyValuePair<K extends keyof KeyTypeMap>(keyId: K): Promise<KeyTypeMap[K]> { const value = keyValuePair[keyId]; if (value) { return value; } throw new Error(`key ${keyId} not found`); } // 调用示例,不需要传泛型,TS自动根据keyId推断返回类型 const aValue = await getKeyValuePair('keyA'); // 自动推断为A类型 const bValue = await getKeyValuePair('keyB'); // 自动推断为B类型
内容的提问来源于stack exchange,提问作者Bobkitten
相关产品推荐
相关产品推荐

