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

如何让TypeScript的keyof支持对象的动态键约束?

问题

我想实现一个从对象中取值的函数,用参数作为对象的键,但发现对象包含动态属性时,keyof无法限制键的范围,反而接受所有字符串。

比如下面的示例,实现了一个对象提取器,允许传入对象的键提取值:

function makeObjectExtractor(
  keyA: string,
) {
  const toExtractFrom = {
    // keyA是动态属性,导致keyof允许任意字符串或数字
    [keyA]: 4,
    keyB: 5
  } satisfies Record<string, number>;

  function getIncrementedVal(param: keyof typeof toExtractFrom) {
    return toExtractFrom[param] + 1;
  }

  return getIncrementedVal;
}

const extractor = makeObjectExtractor('g');

// 这里应该触发TypeScript错误,但因为keyA是动态属性,并没有报错
extractor('asdfasdf');

我需要让TypeScript识别出仅允许'g'和'keyB'作为合法键。如果把所有键硬编码,keyof就能正确限制范围:

function makeObjectExtractor(
) {
  const toExtractFrom = {
    b: 4,
    keyB: 5
  } satisfies Record<string, number>;

  function getIncrementedVal(param: keyof typeof toExtractFrom) {
    return toExtractFrom[param] + 1;
  }

  return getIncrementedVal;
}

const extractor = makeObjectExtractor();

// 这里正确触发错误
extractor('asdfasdf');

// 这里不会报错,符合预期
extractor('b');

这种情况下keyof会正确限制为"b" | "keyB",请问如何让keyof支持动态键?


解决方案

要让TypeScript跟踪动态键的具体类型,需要通过泛型约束参数的类型,替代原本宽泛的string类型:

修改后的代码

function makeObjectExtractor<K extends string>(
  keyA: K,
) {
  const toExtractFrom = {
    [keyA]: 4,
    keyB: 5
  } satisfies Record<K | 'keyB', number>;

  function getIncrementedVal(param: K | 'keyB') {
    return toExtractFrom[param] + 1;
  }

  return getIncrementedVal;
}

const extractor = makeObjectExtractor('g');

// 正确触发TypeScript错误:类型'"asdfasdf"'的参数不能赋给类型'"g" | "keyB"'的参数
extractor('asdfasdf');

// 正常通过类型检查
extractor('g');
extractor('keyB');

核心逻辑

  1. 泛型K extends string会在函数调用时,自动捕获传入keyA的具体字符串字面量(比如'g'),而非宽泛的string类型
  2. 用K | 'keyB'明确限定提取函数的合法键范围,替代原本keyof typeof toExtractFrom的宽泛推断
  3. satisfies Record<K | 'keyB', number>确保对象类型符合预期,同时保留具体键的类型信息

内容的提问来源于stack exchange,提问作者Oved D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 00:15:33