You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 14:53:14