打字稿中的接口:在嵌套对象引用上使用函数参数

interfaces in typescript: use function parameter on a nested object reference

我有这个对象模型:

export interface UpdateDocument {
    updated_at?: string;
    actions?: Actions;
}

export interface Actions {
    update?: Update;
    create?: Create;
}

export interface Update {
    name?: Values;
    priority?: Values;
    engine?: Values;
    fact?: Fact;
}

export interface Fact {
    brand?: Values;
    model?: Values;
    version?: Values;
    year?: Values;
    km?: Values;
    color?: Values;
}

export interface Values {
    old?: any;
    new?: any;
}

export interface Create {
    conditions?: Object;
    recipe?: Object;
}

在这个函数中,我尝试传递一个参数来引用一个对象字段并进行赋值:

async buildUpdateDocument (updateDocument: UpdateDocument) {
        
        let fields: Array<string> = ['name','priority','engine','fact','adjustment'];
        

        fields.forEach((field: string) =>{
            updateDocument.actions!.update![field]!.old = await this.getValue(field)
        })

}

但是我有这个 ts-error: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Update'. 在类型 'Update'.ts(7053)

上找不到参数类型为 'string' 的索引签名

如何在这种引用中传递参数来做赋值?

你们首先指定了一个错误的密钥 adjustment,在 Update 上不存在。此示例使用显式类型 (as const):

let fields = ['name','priority','engine','fact'] as const;

确保在使用 as const.

时不向变量添加类型定义

这里是为了更好地适应 TS 标准而修改的函数。这也解决了原始代码中的 forEach-async 问题。真正正确的结构是对每个 x | undefined 类型进行空值检查,但要覆盖类型错误,可以采用以下方法。

async function buildUpdateDocument (updateDocument: UpdateDocument) {
  const fields: Array<keyof Update> = ['name','priority','engine','fact'];
  await Promise.all(fields.map(async (field) => {
    (((updateDocument.actions as {update: Update}).update)[field] as Values).old = await this.getValue(field);
  }));
}

您当前的代码存在错误,如果您愿意,类型系统会帮助您找到这些错误。首先,adjustment字段在Update类型上不存在,old字段在Fact类型上不存在。

为了正确实现这一点,我将使用 Record 作为数据类型:

const updateFields = ['name', 'priority', 'engine', 'fact'] as const
export type UpdateFields = typeof updateFields[number]
export type Update = Record<UpdateFields, Values>

然后,您的函数将如下所示:

async buildUpdateDocument (updateDocument: UpdateDocument) {

        updateFields.forEach((field) =>{
            updateDocument.actions!.update![field]!.old = await this.getValue(field)
        })

}