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

TypeScript:如何强制泛型函数从obj参数推断泛型类型?

强制泛型T从obj参数推断的解决方案

当然可以解决这个问题!核心思路是调整泛型的推断逻辑,让T严格从传入的obj参数中提取类型,而不是被create函数的返回类型“带偏”。

修改后的实现代码

我们可以通过直接约束泛型参数,从obj的类型中提取值类型,强制create的返回类型与obj的存储类型匹配:

function getOrPut<T extends Record<string, any>>(
  obj: T,
  key: string,
  create: () => NonNullable<T[string]>
): NonNullable<T[string]> {
  const value = obj[key];
  // 用严格的undefined判断,避免0、空字符串等 falsy 值被误判为不存在
  if (value !== undefined) {
    return value;
  } else {
    return obj[key] = create();
  }
};

type Item = { title: string };
type Dictionary = { [key: string]: Item };
const dictionary: Dictionary = {};

// 现在这行代码会直接报错:类型"{}"缺少类型"Item"中的属性"title",符合预期!
// const foo = getOrPut(dictionary, 'foo', () => ({}));

// 正确调用示例
const bar = getOrPut(dictionary, 'bar', () => ({ title: 'Hello World' }));
// bar 的类型是 Item,完全符合预期

原理说明

  1. 泛型参数调整:我们将泛型参数改为T extends Record<string, any>,让T直接代表传入的obj的完整类型,而不是原来的“值类型”。
  2. 提取目标值类型:通过NonNullable<T[string]>,从obj的类型中提取出它的索引值类型,并排除undefined(避免类型污染)。
  3. 强制类型匹配:create函数的返回类型被约束为NonNullable<T[string]>,也就是必须和obj中存储的类型完全兼容,彻底杜绝了create返回类型覆盖obj类型的问题。

额外优化点

原来的if (value)判断存在漏洞:如果obj中存储的是0、''这类 falsy 值,会被误判为“不存在”。改成value !== undefined后,判断逻辑更严谨,只针对“未定义”的场景处理。

内容的提问来源于stack exchange,提问作者Valeriy Katkov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:43:04