【问题标题】:How to implement a pluck function in TypeScript?如何在 TypeScript 中实现 pluck 函数?
【发布时间】:2018-03-17 19:46:15
【问题描述】:

我经常需要从对象中提取属性

const obj = {a:1, b: 2, c: 3};
const plucked = pluck(obj, 'a', 'b'); // {a: 1, b:2}

但是,如果您想要类型安全,这在 TypeScript 中并不容易做到,因为我无法在 TypeScript 中实现具有以下签名的函数,我在 TypeScript's manual 上找到了该函数。

declare function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K>;

我无法获得已编译的版本,这是我尝试过的版本:

function pluck<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
    // Type '{}' is not assignable to type 'Pick<T, K>'.
    const ret: Pick<T, K> = {};
    for (let key of keys) { 
        ret[key] = obj[key];
    }
    return ret; 
}

这是否意味着我需要使用环境声明并在 JS 中声明函数?

【问题讨论】:

  • 是的,没有办法在 TypeScript 类型系统中表示您正在获取一个空对象并以使其与某种类型兼容的方式对其进行修改。通常的解决方法是使用类型断言,如const ret = {} as Pick&lt;T, K&gt;;

标签: typescript generics


【解决方案1】:

我最终在我操作的对象上使用了any,TypeScript 很高兴允许它作为返回值。 See it in action

function pluck<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
    const ret: any = {};
    for (let key of keys) { 
        ret[key] = obj[key];
    }
    return ret; 
}

const less = pluck({ a: 1, b: '2', c: true }, ['a', 'c']);

【讨论】:

  • 是的,不要在代码边界内过于认真地对待类型。它是帮助您提高工作效率的工具。如果您有足够的测试来涵盖用例,则可以使用any。 :)
【解决方案2】:

这里有一个替代选项:

function pluck<T, K extends keyof T>(objs: T, keys: K[]): Pick<T, K> {
  return keys.reduce((result, key) => 
    Object.assign(result, {[key as string]: objs[key]}), {}) as Pick<T, K>;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-02
    • 1970-01-01
    • 2022-06-23
    • 2021-07-17
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 2021-02-27
    相关资源
    最近更新 更多