You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何为TypeScript自定义pick/reject工具函数添加泛型类型?

实现类型安全的pick和reject函数(带自动类型推导)

这是个非常实用的需求——不用依赖Ramda这类库,自己实现的工具函数也能享受到TypeScript的类型推导能力。我们可以通过泛型约束结合TypeScript内置的工具类型,完美实现你想要的效果:

1. pick 函数实现

这个函数会从对象中挑选指定的键,返回只包含这些键的新对象,同时TypeScript能自动推导返回值的类型:

function pick<T extends object, K extends keyof T>(keys: K[], object: T): Pick<T, K> {
  const result = Object.assign(
    {},
    ...keys.map(k => (k in object ? { [k]: object[k] } : {}))
  );
  // 因为Object.assign的返回类型无法自动匹配Pick<T,K>,这里做安全的类型断言
  return result as Pick<T, K>;
}

泛型说明:

  • T extends object:约束传入的第二个参数必须是对象类型
  • K extends keyof T:确保传入的keys数组中的每个元素都是原对象T的有效键,避免传入不存在的键
  • 返回类型Pick<T, K>:TypeScript内置工具类型,专门用来从类型T中提取K指定的键值对集合

2. reject 函数实现

这个函数会排除对象中指定的键,返回剩下的键值对,同样支持自动类型推导:

function reject<T extends object, K extends keyof T>(keys: K[], object: T): Omit<T, K> {
  const result = Object.assign(
    {},
    ...Object.keys(object)
      // Object.keys返回的是string[],这里断言为K是安全的,因为我们只处理T的键
      .filter(k => !keys.includes(k as K))
      .map(k => ({ [k]: object[k] }))
  );
  // 同样做安全的类型断言,匹配Omit<T,K>类型
  return result as Omit<T, K>;
}

泛型说明:

  • 泛型参数TK的约束和pick函数一致
  • 返回类型Omit<T, K>:TypeScript内置工具类型,用来从类型T中移除K指定的键值对

3. 使用示例(符合你的预期)

按照你的测试代码,这样使用就能得到精准的类型推导:

type Item = {title: string, description: string}
const test: { [key: string]: Item } = { 
  a: { title: 'TitleA', description: 'DescriptionA' }, 
  b: { title: 'TitleB', description: 'DescriptionB' }, 
  c: { title: 'TitleC', description: 'DescriptionC' }, 
  d: { title: 'TitleD', description: 'DescriptionD' } 
};

// 注意:如果需要更精确的字面量键类型,给数组加as const断言
const test1 = pick(['a', 'c'] as const, test); 
// 类型推导结果:{ a: Item; c: Item }

const test2 = reject(['a', 'c'] as const, test);
// 类型推导结果:{ b: Item; d: Item }

为什么要加as const

默认情况下,TypeScript会把['a', 'c']这类数组字面量推导为string[],导致泛型K被推断为string(而不是"a" | "c")。加上as const后,数组会被视为只读的字面量数组,TypeScript就能精确推断出K"a" | "c",进而让返回类型更精准。

额外优势

  • 类型安全:如果传入的keys包含原对象不存在的键,TypeScript会直接报错
  • 零依赖:完全基于原生TypeScript和JavaScript实现,不需要引入任何第三方库
  • 自动推导:无需手动指定泛型参数,TypeScript会根据传入的参数自动推导返回值类型

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

火山引擎 最新活动