修改实现接口的对象(通过索引访问)的值时发生类型错误



我是TypeScript的初学者,我不知道TS为什么在=符号的左手边抱怨。

const nonMandatoryFields = [
'address',
'mobilePhone',
'postCode',
'state',
'suburb',
'testMode',
];
interface XeroClientData {
address: string;
firstName: string;
lastName: string;
suburb: string;
postCode: string;
state: string;
country: string;
mobilePhone: string;
email: string;
recordId: string;
testMode: boolean;
}
const sanitiseFields = (fields: XeroClientData) => {
for (const key of nonMandatoryFields) {
// Error on the left hand side
// Element implicitly has an 'any' type 
// because expression of type 'string' can't be used to index type 'XeroClientData'
fields[key] = fields[key as keyof XeroClientData]
? fields[key as keyof XeroClientData]
: '';
}
return fields;
};

正如您所看到的,我已经尝试了keyof运算符,它在右侧运行良好。

如果有人能给我指一份参考文件或指出问题,我将不胜感激。谢谢!


编辑:多亏了@jcalz,我终于解决了这个问题(非常感谢!)。见下文:

const nonMandatoryFields = [
'address',
'mobilePhone',
'postCode',
'state',
'suburb',
] as const;
type NonMandatoryField = typeof nonMandatoryFields[number];
interface XeroClientData {
address: string;
firstName: string;
lastName: string;
suburb: string;
postCode: string;
state: string;
country: string;
mobilePhone: string;
email: string;
recordId: string;
testMode?: boolean; // optional property
}
const sanitiseFields = (fields: XeroClientData) => {
nonMandatoryFields.forEach(<K extends NonMandatoryField>(key: K) => {
fields[key] = fields[key] ? fields[key] : '';
});
return fields;
};

我假设您的nonMandatoryFields都接受string类型(因此""的默认值是合适的),如下所示:

const nonMandatoryFields = [
'address',
'mobilePhone',
'postCode',
'state',
'suburb',
];

如果是这样,那么您需要确保编译器跟踪该数组中字符串的文字类型。现在,编译器推断nonMandatoryFields的类型是string[],这太宽了,它对fields[key]不满意(因为key可以是它所知道的任何string)。

最简单的方法是在初始化器上使用const断言,如下所示:

const nonMandatoryFields = [
'address',
'mobilePhone',
'postCode',
'state',
'suburb',
] as const;

现在nonMandatoryFields的类型是

// const nonMandatoryFields: readonly ["address", "mobilePhone", 
//   "postCode", "state", "suburb"];

这样编译器就可以准确地知道存在哪些值(以及它们在数组中的位置,尽管代码不需要这样做)。

一旦你这样做,一切都开始工作:

const sanitiseFields = (fields: XeroClientData) => {
for (const key of nonMandatoryFields) {
fields[key] = fields[key] ? fields[key] : ''; // okay
}
return fields;
};

编译器知道每个key是接受一个stringXeroClientData的一个密钥。注意,您可以将x ? x : y简化为x || y(除非两次评估x会以某种方式影响事情),所以您可以将其重写为

const sanitiseFields = (fields: XeroClientData) => {
for (const key of nonMandatoryFields) {
fields[key] = fields[key] || ''; // okay
}
return fields;
};

游乐场链接到代码

相关内容

最新更新