以下代码段在Type 'string' is not assignable to type 'never'.(2322)
行中报告了一个错误obj[prop] = value
,我很难理解为什么?
interface fooType {
s: string,
n: number,
}
function bar(value: string, obj: fooType, prop: keyof fooType) {
if (typeof value === 'string') {
obj[prop] = value;
}
}
const foo = {s: '', n: 0};
bar('s', foo, 's');
console.log(foo);
答案 0 :(得分:2)
fooType['s']
是类型string
,fooType['n']
是类型编号,所以obj[prop]
是类型string & number
,因为它是可分配给obj[prop]
的唯一类型。并且string & number
= never
答案 1 :(得分:2)
prop: keyof fooType
表示prop可以为"s"
或"n"
。但是,这两个属性值具有不兼容的类型。因此,打字稿尝试通过找到属性.s
和 .n
的类型的交集来推断可分配给这两个值的值。确实如此:string & number
,它们没有重叠,所以类型为never
。
如果要将参数作为联合(例如"s" | "n"
)输入 ,则需要知道该联合的哪个成员,则需要泛型。
对于通用参数,这里至少需要两个。一个用于您想要更新的属性名称(我们将使用K
作为键),另一个用于值以确保其与属性的类型匹配(我们将使用V
作为值)
您现在可以删除typeof value === 'string'
,因为打字稿将确保该值是该属性的正确类型。
function bar<
K extends keyof fooType,
V extends fooType[K]
>(
value: V,
obj: fooType,
prop: K
) {
obj[prop] = value;
}
const foo = {s: '', n: 0};
bar('string', foo, 's'); // works
bar(123, foo, 'n'); // works
// Should be type errors:
bar('string', foo, 'n') // '"string"' is not assignable to parameter of type 'number'
bar(123, foo, 's') // '123' is not assignable to parameter of type 'string'.
答案 2 :(得分:1)
您需要在此处使用泛型,然后它才能正确匹配类型。
interface fooType {
s: string,
n: number,
}
function bar<
OBJ extends fooType,
KEY extends keyof OBJ,
VAL extends OBJ[KEY]
>(value: VAL, obj: OBJ, prop: KEY) {
obj[prop] = value;
}
const foo = {s: '', n: 0};
bar('s', foo, 's');
console.log(foo);