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

如何使TypeScript泛型类Context实现类型安全,匹配传入键组合?

解决TypeScript register函数的类型安全与自动推断问题

你遇到的Argument of type 'string' is not assignable to parameter of type 'never'错误,本质是因为代码没有正确捕获values参数里的具体键组合类型,导致TypeScript无法识别合法的键值对,最终把参数类型收窄成了never。下面是实现类型安全+自动推断的完整方案:

核心思路

  • 用泛型捕获register传入的values的具体键组合类型,替代宽泛的{ key1: string, key2: string }[]
  • 让Context类基于捕获的键组合类型,约束getValueForKey的参数必须是合法的键对
  • 确保register能自动推断泛型类型,无需开发者手动传入

完整代码实现

// 用泛型T捕获具体的合法键组合类型
type ValidKeyPair<T extends { key1: string; key2: string }> = T;

// 泛型Context类,基于传入的键组合类型约束方法参数
class Context<T extends { key1: string; key2: string }> {
  private keyStore = new Map<string, any>();

  constructor(initialValues: T[]) {
    // 初始化键值存储,可根据实际需求修改逻辑
    initialValues.forEach(pair => {
      this.keyStore.set(`${pair.key1}-${pair.key2}`, /* 对应的值,示例占位 */ null);
    });
  }

  // 约束key1和key2必须是T中存在的合法组合
  getValueForKey<K extends T["key1"], V extends Extract<T, { key1: K }>["key2"]>(
    key1: K,
    key2: V
  ): any {
    return this.keyStore.get(`${key1}-${key2}`);
  }
}

// register函数,自动推断泛型T的类型
function register<T extends { key1: string; key2: string }>(
  values: T[],
  callback: (context: Context<T>) => void
) {
  const context = new Context(values);
  callback(context);
}

// 测试示例
register(
  [
    { key1: "foo", key2: "bar" },
    { key1: "foo", key2: "baz" },
    { key1: "qux", key2: "bar" }
  ],
  (ctx) => {
    // 合法调用:符合传入的键组合,无类型错误
    ctx.getValueForKey("foo", "bar");
    ctx.getValueForKey("qux", "bar");

    // 非法调用:TypeScript会直接报错,拦截不合法的键组合
    // ctx.getValueForKey("foo", "buzz"); // 错误:"buzz"不是"foo"对应的合法key2
    // ctx.getValueForKey("invalid", "bar"); // 错误:"invalid"不是合法的key1
  }
);

代码解释

  1. 泛型自动捕获类型:register的泛型T会自动识别传入values的具体键组合,比如测试示例中T会被推断为{key1: "foo", key2: "bar"} | {key1: "foo", key2: "baz"} | {key1: "qux", key2: "bar"}
  2. 严格的键组合约束:getValueForKey的泛型K和V确保了key2必须是对应key1在T中存在的取值,比如当key1是"foo"时,key2只能是"bar"或"baz"
  3. 零手动泛型传入:开发者调用register时,不需要手动指定泛型类型,TypeScript会根据传入的values自动完成推断

原错误原因分析

你之前的代码出现never类型错误,大概率是因为直接使用了{key1: string, key2: string}这种宽泛的类型,没有用泛型捕获values的具体键组合,导致TypeScript无法确定合法的键值对范围,最终把参数类型约束成了never。通过上面的泛型捕获和约束,就能解决这个问题,同时实现严格的类型安全。

内容的提问来源于stack exchange,提问作者marko-rutter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 01:47:05