我想动态修改对象中的值:
interface type {
id: number;
name: string;
}
const formFields: (keyof type)[] = ['id', 'name']
let test: type = {
id: 0,
name: `name`
}
let data: string[] = ['1', 'Name']
for (let i = 0; i < data.length; i++) {
const field = formFields[i];
if (typeof test[field] === 'number') {
test[field] = Number(data[i]);
} else if (typeof test[field] === 'string') {
test[field] = data[i];
}
}
但我无法避免这个错误:
Type 'number' is not assignable to type 'never'.(2322)
虽然不影响实际操作。
在 JS/TS 中,属性可能有 getter 和 setter,并且它们的类型可能不同。您检查 getter 返回的类型,但 setter 可能接受不同的类型。看这个例子:
const obj = {
val: "",
get prop(): string {
return this.val;
},
set prop(val: number) {
this.val = val.toString()
},
}
// The following assignment does not compile:
if (typeof obj.prop === "string") { // here prop looks like a string property
obj.prop = "str" // but here prop is already a number property
}
这个例子应该可以阐明为什么 TS 会有这样的行为。
下面有两个选项供您解决问题。
第一个选项保持逻辑不变并绕过 TS 错误:
interface type {
id: number;
name: string;
}
const formFields: (keyof type)[] = ['id', 'name']
let test: type = {
id: 0,
name: `name`
}
let data: string[] = ['1', 'Name']
for (let i = 0; i < data.length; i++) {
const field = formFields[i];
if (typeof test[field] === 'number') {
setTestField(field, Number(data[i]))
} else if (typeof test[field] === 'string') {
setTestField(field, data[i])
}
}
function setTestField<T extends keyof type>(key: T, value: type[T]): void {
test[key] = value
}
第二个选项是稍微重写你的逻辑:
interface type {
id: number;
name: string;
}
const formFields: (keyof type)[] = ['id', 'name']
let test: type = {
id: 0,
name: `name`
}
let data: string[] = ['1', 'Name']
for (let i = 0; i < data.length; i++) {
const field = formFields[i];
switch (field) {
case 'id':
test.id = Number(data[i]);
break;
case 'name':
test.name = data[i]
break;
}
}
也许其中之一适合您的情况。