How to Omit “DELETE” many properties from an Object?

孤人 提交于 2020-05-29 11:11:07

问题


I have two methods that return the following types Pick<T, K> and Omit<T, K> where Omit is type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>. I have some trouble when it comes to removing multiple properties from an object.

I have a method pickOne that selects one property from an object, a method pickMany that picks multiple properties from an object and a method omitOne that removes one property from an Object. I would like to have a OmitMany method to remove multiple properties from an Object, but I got stuck when fixing the type errors in the method.

Implementation of the methods:

export let pickOne = <T, K extends keyof T>(entity: T, props: K ): Pick<T, K> => {
    return { [props] : entity[props] } as Pick<T, K>
}

export let pickMany = <T, K extends keyof T>(entity: T, props: K[]) => {
   return props.reduce((s, prop) => (s[prop] = entity[prop], s) , {} as Pick<T, K>)
}

export let omitOne = <T, K extends keyof T>(entity: T, prop: K): Omit<T, K> => {
    const { [prop]: deleted, ...newState} = entity
    return newState
}

// And the OmitMany for so far I tried, the problem is with storing the entity
// in a temporary variable. This function only omits the last property in the
// the array. I would like an implementation simular to pickMany.
export let omitMany = <T, K extends keyof T>(entity: T, props: K[]): Omit<T, K> => {
    let result = entity as Omit<T, K>
    props.forEach(prop => {
        result = omitOne(entity, prop)
    })
    return result
}

I expect the output of omitMany({x: 1, y: 2, z: 3, r: 4}, ['x', 'y']) to be an object of type {z: number, r: number}, but right know the output is an object of type {x: number, z: number, r: number}


回答1:


Your issue has little to do with typescript. The types work out as you expect them to for omitMany, the only problem is that at run-time it does not remove all the properties you expect it to and this is cause by the fact that you call omitOne on entity instead of the previous result. This requires some type assertions unfortunately, but it will work:

type Omit<T, K> = Pick<T, Exclude<keyof T, K>>

let omitOne = <T, K extends keyof T>(entity: T, prop: K): Omit<T, K> => {
    const { [prop]: deleted, ...newState } = entity
    return newState
}

let omitMany = <T, K extends keyof T>(entity: T, props: K[]): Omit<T, K> => {
    let result = entity as Omit<T, K>
    props.forEach(prop => {
        result = omitOne(result, prop as unknown as keyof Omit<T, K>) as Omit<T, K>
    })
    return result
}

let o = omitMany({ x: 1, y: 2, z: 3, r: 4 }, ['x', 'y'])
console.log(o)

Playground



来源:https://stackoverflow.com/questions/56255212/how-to-omit-delete-many-properties-from-an-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!