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

TypeScript中能否为泛型返回函数传递动态键?

如何实现支持动态泛型参数的Omit/Pick工具函数

你遇到的问题根源在于:当把fields定义为Array<keyof T>时,TypeScript会将typeof fields[number]推断为整个keyof T(也就是对象的所有键),而不是你实际传入的具体键集合。要解决这个问题,关键是通过额外的泛型参数捕获动态传入的键,让TS能精准推断泛型工具类型需要的参数。

1. 实现支持动态K的Omit函数

直接新增泛型K并约束为keyof T,让TS从传入的数组字面量中自动推断出具体的键联合类型:

const removeKeys = <T extends Record<string, unknown>, K extends keyof T>(
  data: T,
  fields: K[]
): Omit<T, K> => {
  const result = { ...data };
  for (const key of fields) {
    delete result[key];
  }
  return result;
};

使用示例:

type MyType = {
  firstKey: string,
  secondKey: string,
  thirdKey: string
}

const completeObject: MyType = {
  firstKey: 'value1',
  secondKey: 'value2',
  thirdKey: 'value3'
}

const omittedObject = removeKeys(completeObject, ['secondKey', 'thirdKey']);
// omittedObject 自动推断为 Omit<MyType, 'secondKey' | 'thirdKey'>
// 即类型为 { firstKey: string }

2. 扩展到Pick函数

同样的思路可以直接复用在Pick场景:

const pickKeys = <T extends Record<string, unknown>, K extends keyof T>(
  data: T,
  fields: K[]
): Pick<T, K> => {
  const result = {} as Pick<T, K>;
  for (const key of fields) {
    result[key] = data[key];
  }
  return result;
};

const pickedObject = pickKeys(completeObject, ['firstKey', 'thirdKey']);
// pickedObject 类型为 Pick<MyType, 'firstKey' | 'thirdKey'>

3. 适配自定义泛型类型

这种方式同样适用于自定义泛型工具类型,比如我们定义一个保留指定类型键的工具类型:

// 自定义泛型:只保留值类型为V的键
type KeepKeysByType<T, V> = {
  [K in keyof T as T[K] extends V ? K : never]: T[K]
};

const keepKeysByType = <T extends Record<string, unknown>, V>(
  data: T,
  typeGuard: (val: T[keyof T]) => val is V
): KeepKeysByType<T, V> => {
  const result = {} as KeepKeysByType<T, V>;
  for (const key in data) {
    if (typeGuard(data[key])) {
      result[key as keyof typeof result] = data[key];
    }
  }
  return result;
};

// 使用示例
const mixedObject = {
  str1: 'a',
  num1: 1,
  str2: 'b',
  num2: 2
};

const stringKeysOnly = keepKeysByType(mixedObject, (val): val is string => typeof val === 'string');
// stringKeysOnly 类型为 { str1: string; str2: string }

核心思路总结

通过显式声明额外的泛型参数(比如K),让TypeScript从传入的参数(比如键数组)中捕获具体的类型信息,而不是依赖宽泛的自动推断。这种模式可以通用在所有需要动态指定泛型参数的场景,包括官方工具类型和自定义泛型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 07:53:14