Reputation: 13803
I have tried to read how to delete a property from an object in here: How do I remove a property from a JavaScript object?
it should use delete
, I try it like this
const eventData = {...myEvent}; // myEvent is an instance of my `Event` class
delete eventData.coordinate; // I have error in here
but I have error like this
The operand of a 'delete' operator must be optional.ts(2790)
and then I read this : Typescript does not infer about delete operator and spread operator?
it seems to remove that error is by changing my tsconfig.json file using
{
"compilerOptions": {
...
"strictNullChecks": false,
}
...
}
but if I implement this, I will no longer have null checking
so how to delete a property from an object in Typescript without the operand of a 'delete' operator must be optional error?
Upvotes: 19
Views: 34447
Reputation: 13
@Loïc Goyet's solution also works when using an array of properties as input:
function popProperty<T extends Record<string, unknown>, K extends keyof T>(
obj: T,
properties: K[],
): Omit<T, K> {
const result = { ...obj };
for (const key of properties) {
delete result[key];
}
return result;
}
const x = popProperty({ a: 1, b: 2, c: 3 }, ['a', 'b']);
// const x: Omit<{
// a: number;
// b: number;
// c: number;
// }, "a" | "b">
Upvotes: 0
Reputation: 14890
Avoid the error by casting to any:
const user = {
firstName: 'billy',
middleName: 'the',
lastName: 'kid'
};
delete (user as any).middleName
console.log(user)
// { firstName: 'billy', lastName: 'kid' }
Upvotes: 1
Reputation: 73
As many people has already pointed out, the following is a workable but not recommending way as it is not type-safe:
/* eslint-disable @typescript-eslint/no-explicit-any */
delete (eventData as any).coordinate;
Upvotes: -3
Reputation: 750
Personally, I created a specific function taking advantage of generics, and it worked well!
const removeAttrFromObject = <O extends object, A extends keyof O>(
object: O,
attr: A
): Omit<O, A> => {
const newObject = { ...object }
if (attr in newObject) {
delete newObject[attr]
}
return newObject
}
The two generics O
and A
are making all the magic, especially the A
generic: extends keyof O
says "the second parameter must be an attribute from the object".
Then inside the function, TypeScript knows for sure that attr
is an attribute from the object
. I double-check with the attr in newObject
if statement, in order to make sure at runtime everything is fine too. Just pure defensive programming.
The const newObject = { ...object }
is here to make sure we don't modify the reference passed as arg, but return a new reference instead. It's some leftovers from my functional programming old days.
Now if we try the function :
const test = removeAttrFromObject({ a: 1, b: 2 }, 'a')
// returns as type `Omit<{a: 1, b: 2}, 'a'>` which equals `{a: 1}`
const test2 = removeAttrFromObject({ a: 1, b: 2 }, 'c')
// TypeScript raise an error as `'c'` is not a key from the object passed
Upvotes: 3
Reputation: 37918
Typescript warns you about breaking the contract (the object won't have the required property anymore). One of the possible ways would be omitting the property when you cloning the object:
const myEvent = {
coordinate: 1,
foo: 'foo',
bar: true
};
const { coordinate, ...eventData } = myEvent;
// eventData is of type { foo: string; bar: boolean; }
Operands for
delete
must be optional. When using thedelete
operator instrictNullChecks
, the operand must beany
,unknown
,never
, or be optional (in that it containsundefined
in the type). Otherwise, use of thedelete
operator is an error.
Upvotes: 35
Reputation: 5112
What the error is telling you is that coordinate
is not an optional property of that object (that is it can be undefined) and you are trying to delete it.
You could have deleted it if it was optional
coordinate?: FirebaseFirestore.Geopoint
It seems to have been introduced after version 4.0, you can read more about it here.
Upvotes: 0
Reputation: 39
You can delete if the property is optional
interface OptionalCoordinate {
coordinate?
}
const eventData: OptionalCoordinate = {...myEvent}; // myEvent is an instance of my `Event` class
// ok to delete
delete eventData.coordinate;
Upvotes: 2