typescript - 修改实现接口(interface)的对象(通过索引访问)的值时出现类型错误

标签 typescript

我是 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',
];

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

最简单的方法是使用 const assertion在初始化器上,像这样:

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 都是 XeroClientData 的一个键,它接受一个 string。请注意,您可以简化 x 吗? x : yx || y (除非评估 x 两次以某种方式影响事情),所以你可以将其重写为

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

Playground link to code

关于typescript - 修改实现接口(interface)的对象(通过索引访问)的值时出现类型错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74684429/

相关文章:

javascript - Typescript - 对象的括号索引不会产生错误

javascript - 具有依赖性的 React useState Hook

typescript - 替换通用接口(interface)类型参数

javascript - 来自函数参数的动态 Typescript 对象属性

typescript - 编译时正常,在带有 webpack 的 typescript 中使用命名空间中的类时出现运行时错误

javascript - 根据其嵌套数组值过滤数组

typescript 模板文字作为界面键

javascript - Angular 8 : Reactive Form Automap and PatchValue Set Member data

javascript - 错误 TypeError : Cannot read property 'subscribeNewsletter' of undefined at newsletter. component.ts.NewsletterComponent.subscribeNewsletter

typescript - 在将 aws cdk 与 appsync 结合使用时,如何向 graphql 架构添加突变并防止部署失败?