TypeScript类型安全的省略功能 [英] TypeScript Type-safe Omit Function

查看:112
本文介绍了TypeScript类型安全的省略功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用普通打字稿复制lodash的_.omit函数. omit应该返回一个对象,该对象的某些属性已删除,这些属性是通过第一个出现的对象参数之后通过参数指定的.

I want to replicate lodash's _.omit function in plain typescript. omit should return an object with certain properties removed specified via parameters after the object parameter which comes first.

这是我的最佳尝试:

function omit<T extends object, K extends keyof T>(obj: T, ...keys: K[]): {[k in Exclude<keyof T, K>]: T[k]} {
    let ret: any = {};
    let key: keyof T;
    for (key in obj) {
        if (!(keys.includes(key))) {
            ret[key] = obj[key];
        }
    }
    return ret;
}

哪个给我这个错误:

Argument of type 'keyof T' is not assignable to parameter of type 'K'.
  Type 'string | number | symbol' is not assignable to type 'K'.
    Type 'string' is not assignable to type 'K'.ts(2345)
let key: keyof T

我对错误的解释是:

  1. 由于键是keyof T并且T是对象,所以键可以是symbolnumberstring.

  1. Since key is a keyof T and T is an object, key can be a symbol, number or string.

由于我使用了for in循环,因此键只能是string,但是如果我传入数组,例如includes可能会使用number?我认为.那意味着这里有类型错误?

Since I use the for in loop, key can only be a string but includes might take a number if I pass in an array, for example? I think. So that means there's a type error here?

任何关于为什么不起作用以及如何使其起作用的见解都将受到赞赏!

Any insights as to why this doesn't work and how to make it work are appreciated!

推荐答案

interface Omit {
    <T extends object, K extends [...(keyof T)[]]>
    (obj: T, ...keys: K): {
        [K2 in Exclude<keyof T, K[number]>]: T[K2]
    }
}

const omit: Omit = (obj, ...keys) => {
    let ret = {} as {
        [K in keyof typeof obj]: (typeof obj)[K]
    };
    let key: keyof typeof obj;
    for (key in obj) {
        if (!(keys.includes(key))) {
            ret[key] = obj[key];
        }
    }
    return ret;
}

为方便起见,我将大多数输入拉到了界面上.

For convenience I've pulled most of the typings to an interface.

问题在于,K被(正确的时态?)推断为 tuple ,而不是按键的 union .因此,我相应地更改了它的类型约束:

The problem was that K has been being (correct tense?) inferred as a tuple, not as a union of keys. Hence, I changed it's type constraint accordingly:

[...(keyof T)[]] // which can be broke down to:
keyof T // a union of keys of T
(keyof T)[] // an array containing keys of T
[] // a tuple
[...X] // a tuple that contains an array X

然后,我们需要将元组K转换为一个并集(以便将其从keyof T转换为Exclude).这是用K[number]完成的,我想这是不言而喻的,它与T[keyof T]创建T值的并集相同.

Then, we need to transform the tuple K to a union (in order to Exclude it from keyof T). It is done with K[number], which is I guess is self-explaining, it's the same as T[keyof T] creating a union of values of T.

查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆