У меня есть два метода, которые возвращают следующие типы Pick<T, K>
и Omit<T, K>
, где Omit — это type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
. У меня возникают проблемы с удалением нескольких свойств объекта.
У меня есть метод pickOne
, который выбирает одно свойство из объекта, метод pickMany
, который выбирает несколько свойств из объекта, и метод omitOne, который удаляет одно свойство из объекта. Я хотел бы иметь метод OmitMany для удаления нескольких свойств из объекта, но я застрял при исправлении ошибок типа в методе.
Реализация методов:
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
}
Я ожидаю, что вывод omitMany({x: 1, y: 2, z: 3, r: 4}, ['x', 'y'])
будет объектом типа {z: number, r: number}
, но точно знаю, что вывод является объектом типа {x: number, z: number, r: number}
Ваша проблема имеет мало общего с машинописью. Типы работают так, как вы ожидаете, для omitMany
, единственная проблема заключается в том, что во время выполнения он не удаляет все свойства, которые вы ожидаете, и это вызвано тем фактом, что вы вызываете omitOne
на entity
вместо предыдущего результата . К сожалению, это требует некоторых утверждений типа, но это сработает:
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)
Начиная с TS 3.5 и стандартного типа Omit
:
function omit<T, K extends keyof T>(obj: T, ...props: K[]): Omit<T, K> {
return props.reduce((o, k) => { delete o[k]; return o; }, { ...obj });
}