11

In TypeScript it is quite simple to clone an object:

const a = {...b}

or clone and update

const a = {...b, c: 'd'}

So for example, I have this code:

const a = {
    'something': 1,
    'e': 2,
};
const c = 'something';
delete a[c];

Is there a nice way to delete a property of that object, instead of using the traditional delete a[c] way? (of course also not a[c] = undefined)

Nguyen Phong Thien
  • 3,237
  • 1
  • 15
  • 36

3 Answers3

26

You're looking for combination of computed property names and destructuring. More info here

const a = {
    'something': 1,
    'e': 2,
};

const c = 'something';

const { [c]: _, ...withoutC } = a;

Here we're putting value of property something (taken from c variable) into _ variable and all the other props go to withoutC variable. The fact that c defined as const allows typescript to infer the type of withoutC properly.

Aleksey L.
  • 35,047
  • 10
  • 74
  • 84
8

Rather than deleting the property from a, use destructured assignment to create a new object without that property:

const {c, ...b} = a;

After this b will contain all members of a except c.

Given that a is some type, say, { c: string, d: string } the types of c and b will be inferred to be string and { d: string } respectively. Of course, if you have to explicitly write these type annotations, using an Omit type as @Nurbol Alpybayev suggests is usually a lot better than having to spell out the types in long form.

You can rename c to avoid conflicts with another name using this syntax:

const {c: someOtherName, ...b} = a;

The above method will work if you know the property name at compile time. If that's not the case in your scenario, then the TypeScript compiler can't really help you that much because it won't be able to determine the result type of the operation.

You'd be better off typing a as { [k: string]: number }, in which case delete a[c] would be fine, or you could use something like the following:

const exclude = <T>(map: { [k: string]: T }, omitted: string[]): { [k: string]: T } =>
  return Object.getOwnPropertyNames(a)
    .filter(k => omitted.indexOf(k) >= 0)
    .reduce((a, k) => (a[k] = map[k], a), {})
};
var b = exclude(a, ["c"]);
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • Really close, but in my case, it is a bit more complicated. For example: ```const a = { 'something': 1, 'e': 2, }; const c = 'something'; const { 'something': undefined, ...b } = a;``` work, but ```const a = { 'something': 1, 'e': 2, }; const c = 'something'; const { c: undefined, ...b } = a;``` doesn't – Nguyen Phong Thien Feb 18 '19 at 14:37
  • so the point here is ```c``` is not a string ```'c'```. It is a variable ```const c = 'something'```. Hope this time it is clear enough – Nguyen Phong Thien Feb 18 '19 at 14:38
  • @NguyenPhongThien I'm still not sure if I understand the problem. If the property that you want to delete is known at compile time, my method will work. If the property name isn't known at compile time, the result type of the expression cannot be determined (except for mapped types like `{ [k: string]: number }`). – p.s.w.g Feb 18 '19 at 15:15
  • no, it is not a problem at all. I'm finding a nicer way to clone an object and delete a key from that, instead of ```const a = {...b}; delete a[c];``` and sometime later ```b = {...a}```. Because I don't want to mutate the original object for a while. But if it is not possible, it will still not be a big issue – Nguyen Phong Thien Feb 18 '19 at 15:21
  • @NguyenPhongThien I've added one more solution that's more idiomatic than `const a = {...b}; delete a[c];`. – p.s.w.g Feb 18 '19 at 15:40
0

Sure! You can do this using Omit type:

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

type DeleteBar = Omit<{bar: 123, baz: 123}, 'bar'> // {baz: 123}

P.S. I realized that you might have asked about values, not types. You should have ask about javascript probably, not typescript.

Nurbol Alpysbayev
  • 19,522
  • 3
  • 54
  • 89
  • 1
    it doesn't really work, could you please let me know how does it work in this case: ```const a = { 'something': 1, 'e': 2, }; const c = 'something'; delete a[c];``` – Nguyen Phong Thien Feb 18 '19 at 14:39