У меня есть вопрос о поведении ключевого слова delete
в Javascript или Typescript.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete
Мне нужен способ выбора свойств из объекта и способ пропуска свойств из объекта.
Typescript поставляется со сборкой типа Pick
https://www.typescriptlang.org/docs/handbook/advanced-types.html
type Pick<T, K extends keyof T> = { [P in K]: T[P]; }
Противоположностью Pick
является Omit
, которая может быть реализована какthis:
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof 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 omitMany = <T, K extends keyof T>(entity: T, props: K[]):
Omit<T, K> => {
return props.reduce((s, prop) => (delete s[prop] ,s), entity)
}
Для Omit я использовал ключевое слово delete, вначале оно работало, но теперь я сталкиваюсь с некоторыми проблемами.Основная проблема заключается в том, что для omitMany
исходный объект изменяется.Что вызывает проблемы с сохранением исходных данных и сохранением состояния позже в моей программе.
Я написал простой пример, иллюстрирующий мою проблему:
// First I make some interface that contains some structure for data
interface SomeObject { x: string, y: number, z: boolean }
// Initialize object1 with properties x, y and z, containing the important data
// I want to preserve all the data in object1 throug the entire program
let object1: SomeObject = { x: "something", y: 0, z: false }
// I can print all properties of object1
console.log(`Object 1: x = ${object1.x}, y = ${object1.y}, z = ${object1.z}`)
// OUTPUT: "Object 1: x = something, y = 0, z = false"
// omit or delete property 'x' from object 1, defining object 2
let object2 = omitMany(object1, ["x"]) // The type of object2 is: {y: number, z: boolean}
// Here I can only get properties z and y, because x has been omited
// Calling: object2.x gives an compile error
console.log(`Object 2: y = ${object2.y}, z = ${object2.z}`)
// OUTPUT: Object 2: y = 0, z = false (as expected)
// Everything works fine from here, but...
// When I recall omitMany on object1 the following happens:
// Initialize object3 from object1, removing 'x' from an object where x = undefined
let object3 = omitMany(object1, ["x"]) // This code compiles, omiting 'x' from object2 gives an compiler error
//Printing object3 does show no problems, since it satisfies the expected result. Remove 'x' and keep 'y' and 'z'
console.log(`Object 3: y = ${object3.y}, z = ${object3.z}`)
// OUTPUT: Object 3: y = 0, z = false
// But when I print object1 again
console.log(`Object 1: x = ${object1.x}, y = ${object1.y}, z = ${object1.z}`)
// OUTPUT: Object 1: x = undefined, y = 0, z = false
// We lost the data of 'x'!!!
// I also ran into problems when I try to pick property 'x' from the original object1
let object4 = pickMany(object1, ["x"]) // The type of object4 is {x: string}
// When I print 'x' from object4 it is still undefined
console.log(`Object 4: x = ${object4.x}`)
// OUTPUT: Object 4: x = undefined
Я понимаю, что это связано с поведением delete
, но есть ли другой способ удаления свойствот объекта, не теряя информацию исходного объекта?Так что с сохранением всех значений и свойств.
Эту проблему можно решить с помощью временной переменной, но сначала я хотел посмотреть, есть ли другие решения.