如何获取Record中指定项的泛型类型并应用于函数参数?
如何根据ApiKey自动推导set函数的body参数类型?
现有代码
// 自定义各key对应的接口 interface Alert { name: string; }; interface Notice { code: number; }; // 允许的key集合 type ApiKey = 'alert' | 'notice'; // 配置类型 type ApiConfig<T> = { endpoint: string; myType: T }; // 定义各key对应的配置映射(实际代码中由函数生成,但最终是常量) const ApiMap = { alert: { endpoint: '/alerts', } as ApiConfig<Alert>, notice: { endpoint: '/notices', } as ApiConfig<Notice> }; // 根据key返回对应的配置类型(带泛型) export type ApiConfigForKey<A extends ApiKey> = typeof ApiMap[A]; // 根据key返回带类型的配置(带泛型) export const getConfig = <E extends ApiKey>(apiKey: E ): ApiConfigForKey<E> => ApiMap[apiKey]; const alertApi = getConfig('alert'); // 类型正确且带泛型 const noticeApi = getConfig('notice'); // 类型正确且带泛型
需求
实现set函数,根据传入的apiKey自动推导第二个参数body的类型为对应ApiConfig项的泛型类型,调用时需满足:
set('alert', { name: 'My name' } );符合Alert类型,正常通过set('notice', { code: 500 } );符合Notice类型,正常通过set('alert', { code: 500 } );类型不匹配,报错set('notice', { name: 'My name' } );类型不匹配,报错
解决方案
步骤1:定义辅助类型提取泛型参数
通过TypeScript的条件类型推断,从ApiConfig<T>中提取泛型T:
// 辅助类型:从ApiConfig<T>中提取泛型参数T type ExtractApiConfigType<C> = C extends ApiConfig<infer T> ? T : never;
步骤2:实现set函数
利用辅助类型和已有的ApiConfigForKey类型,自动推导body的类型:
// 实现set函数,自动推导body的类型 const set = <E extends ApiKey>(apiKey: E, body: ExtractApiConfigType<ApiConfigForKey<E>>) => { // 可添加业务逻辑,比如调用接口等 const config = getConfig(apiKey); console.log(`请求地址:${config.endpoint},请求参数:`, body); };
验证效果
// 正常调用 set('alert', { name: 'My name' }); // ✅ body类型为Alert,符合要求 set('notice', { code: 500 }); // ✅ body类型为Notice,符合要求 // 错误调用(类型不匹配) set('alert', { code: 500 }); // ❌ 类型错误:缺少Alert必需的name属性 set('notice', { name: 'My name' }); // ❌ 类型错误:缺少Notice必需的code属性
原理说明
ExtractApiConfigType<C>通过infer关键字,在条件类型中自动提取ApiConfig的泛型参数T;ApiConfigForKey<E>根据传入的apiKey(类型为E)返回对应的ApiConfig实例类型;- 函数调用时,TypeScript会根据
apiKey的值推导E的具体类型,再通过辅助类型得到body的目标类型,实现自动校验。
内容的提问来源于stack exchange,提问作者Ewan
相关产品推荐
相关产品推荐

