Typescript Can't Assign Value To Object Key With Hasownproperty Type Narrowing
I defined hasOwnProperty with type narrowing: function hasOwnProperty< Obj extends Record, Prop extends PropertyKey, >( obj: Obj, prop: Prop, ): ob
Solution 1:
function hasOwnProperty<
ObjextendsRecord<string, any>,
PropextendsPropertyKey,
>(
obj: Obj,
prop: Prop,
): obj is Obj & Record<Prop, any> {
returnObject.prototype.hasOwnProperty.call(obj, prop);
}
function addProp<T>(obj: Record<string, any>, key: string, val: any) {
if (!hasOwnProperty(obj, key)) {
obj // <---------------- is infered to never
obj[key] = val;
}
}
In your case, obj
after condition statement infered to never
.
Why?
Because type of key
is a string and !hasOwnProperty(obj, key)
means that obj
has no more string
keys.
How to fix it ?
You can just add explicit generic for key
argument.
function addProp<T, Propextends string>(obj: Record<string, any>, key: Prop, val: any) {
if (!hasOwnProperty(obj, key)) {
obj[key] = val;
return obj
}
return obj
}
const x = addProp({}, 'a', 42) // Record<string, any> & Record<"a", any>
Here, in my blog, you can find more issues with mutations in typescript
@captain-yossarian's answer works for functions where I can have a generic for the key. However, in places where I can't use a generic, it still doesn't work (see edit)
This example just can't work:
constobj: Record<string, number> = {};
const key = 'key';
if (!hasOwnProperty(obj, key)) {
obj[key] = 123;
}
SInce you assume that key
property is optional in obj
, you should use Partial
:
constobj: Partial<Record<PropertyKey, number>> = {};
const key = 'key';
if (!hasOwnProperty(obj, key)) {
const x = obj
obj[key] = 123; // ok
}
Post a Comment for "Typescript Can't Assign Value To Object Key With Hasownproperty Type Narrowing"