TypeScript能否从函数返回值推断泛型?构建函数传回调时推断失败
问题原因分析
这是泛型参数声明位置与TypeScript类型推断逻辑不匹配导致的问题,并非语言限制。
当buildStore的泛型<Key, Result>声明在函数层面时,TypeScript会要求传入的构建函数必须返回Options<Key, Result>类型,但此时构建函数的返回值类型尚未被推断出来,无法反向推导Key和Result的具体类型,最终只能默认推断为unknown和any,导致类型失效。
解决方案
方案一:直接约束泛型为Options类型
让buildStore的泛型参数直接代表整个Options对象类型,TypeScript会自动从构建函数的返回值中推断出完整的类型信息:
interface Options<Key, Result> { key: Key; format(key: Key): Result; } function buildStore<T extends Options<any, any>>(options: () => T) { return options(); } const store = buildStore(() => { return { key: { id: 32 }, format(key) { // key被正确推断为{ id: number } return key.id.toString(); } }; }); // store类型自动推断为Options<{ id: number }, string> store.format({ id: 10 }); // 无报错,正常工作
方案二:用infer提取泛型参数
如果需要单独获取Key和Result的类型,可以通过ReturnType和条件类型的infer关键字从构建函数的返回值中提取:
interface Options<Key, Result> { key: Key; format(key: Key): Result; } function buildStore<T extends () => Options<any, any>>(options: T) { type ReturnedOptions = ReturnType<T>; type ExtractedKey = ReturnedOptions extends Options<infer K, any> ? K : never; type ExtractedResult = ReturnedOptions extends Options<any, infer R> ? R : never; const result = options(); return result as Options<ExtractedKey, ExtractedResult>; } const store = buildStore(() => { return { key: { id: 32 }, format(key) { return key.id.toString(); } }; }); store.format({ id: 10 }); // 正常工作
核心逻辑
TypeScript的泛型推断是从实参到泛型参数的正向推导流程。当你把泛型参数拆分为Key和Result并声明在buildStore层面时,实参(构建函数)的返回值类型还未确定,无法满足正向推导的要求;而调整泛型约束为整个Options类型后,TypeScript可以先推断构建函数的返回值,再确定泛型的具体类型,从而完成正确的类型推断。
内容的提问来源于stack exchange,提问作者FCStrike
相关产品推荐
相关产品推荐

