在typescript中编写类型安全的“pick”函数

tkclm6bt  于 2023-03-13  发布在  TypeScript
关注(0)|答案(6)|浏览(200)

lodash具有pick函数,该函数的用法如下:

var object = { 'a': 1, 'b': '2', 'c': 3 };

_.pick(object, ['a', 'c']);
// => { 'a': 1, 'c': 3 }

我想用 typescript 写一个类型安全的版本。
此函数的用法应为

pick(object, o => o.a, o.b)

这样做的目的是避免两次指定相同的键,同时保持类型安全。
这有可能实现吗?

svdrlsy4

svdrlsy41#

听起来你可能在找Pick type。像这样的东西对你有用吗?

function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K> {
  const ret: any = {};
  keys.forEach(key => {
    ret[key] = obj[key];
  })
  return ret;
}

const o = {a: 1, b: '2', c: 3}
const picked = pick(o, 'b', 'c');

picked.a; // not allowed
picked.b  // string
picked.c  // number
ercv8c1e

ercv8c1e2#

使用Object.fromEntries(es2019):

function pick<T extends object, K extends keyof T> (base: T, ...keys: K[]): Pick<T, K> {
  const entries = keys.map(key => ([key, base[key]]));
  return Object.fromEntries(entries);
}
ego6inou

ego6inou3#

下面是我使用Object.assign()

function pick<T, K extends keyof T>(object: T, keys: K[]): Pick<T, K> {
  return Object.assign(
    {},
    ...keys.map(key => {
      if (object && Object.prototype.hasOwnProperty.call(object, key)) {
        return { [key]: object[key] };
      }
    })
  );
};
nwsw7zdq

nwsw7zdq4#

lodash类型定义使用Pick来传播 prop ,所以不需要手工定义,只需要使用npm i --save-dev @types/lodash或者yarn add -D @types/lodash安装即可。

q9yhzks0

q9yhzks05#

在这里我的,延伸@巴渝卡尼亚回答:

function pick<T extends Record<string | number | symbol, T>, K extends keyof T>(
  object: T,
  keys: K[]
): Pick<T, K> {
  return Object.assign(
    {},
    ...keys.map((key: K) => {
      return { [key]: object[key] };
    })
  );
}
4xrmg8kj

4xrmg8kj6#

根据Ethan.Roday的回答,我做了一些修改。使用Array.reduce并去掉any类型。

export function pick<T, K extends keyof T>(obj: T, keys: K[]) {
    return keys.reduce((acc, val) => {
        return (acc[val] = obj[val]), acc;
    }, {} as Pick<T, K>);
}

相关问题