[英]Typescript can't assign value to object key with hasOwnProperty type narrowing
我用类型缩小定义了hasOwnProperty
:
function hasOwnProperty<
Obj extends Record<string, any>,
Prop extends PropertyKey,
>(
obj: Obj,
prop: Prop,
): obj is Obj & Record<Prop, any> {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
我期望这样一个简单的函数可以工作:
function addProp<T>(obj: Record<string, any>, key: string, val: any) {
if (!hasOwnProperty(obj, key)) {
obj[key] = val;
}
}
但是,我得到Type 'any' is not assignable to type 'never'.
这是有道理的,因为类型缩小是说obj
中不存在key
。 但是,这不应阻止我添加密钥。 有什么我做错了吗?
编辑:此外,它也不能在函数之外工作:
const obj: Record<string, number> = {};
const key = 'key';
if (!hasOwnProperty(obj, key)) {
obj[key] = 123;
}
function hasOwnProperty<
Obj extends Record<string, any>,
Prop extends PropertyKey,
>(
obj: Obj,
prop: Prop,
): obj is Obj & Record<Prop, any> {
return Object.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;
}
}
在您的情况下,条件语句后的obj
推断为never
。 为什么?
因为key
类型是字符串,而!hasOwnProperty(obj, key)
意味着obj
没有更多的string
键。
如何解决?
您可以为key
参数添加显式泛型。
function addProp<T, Prop extends 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>
在这里,在我的博客中,您可以在打字稿中找到更多关于突变的问题
@captain-yossarian 的答案适用于我可以为密钥使用泛型的函数。 但是,在我不能使用泛型的地方,它仍然不起作用(请参阅编辑)
这个例子是行不通的:
const obj: Record<string, number> = {};
const key = 'key';
if (!hasOwnProperty(obj, key)) {
obj[key] = 123;
}
因为您假设key
属性在obj
是可选的,所以您应该使用Partial
:
const obj: Partial<Record<PropertyKey, number>> = {};
const key = 'key';
if (!hasOwnProperty(obj, key)) {
const x = obj
obj[key] = 123; // ok
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.