【问题标题】:interfaces in typescript: use function parameter on a nested object reference打字稿中的接口:在嵌套对象引用上使用函数参数
【发布时间】:2021-06-16 02:57:03
【问题描述】:

我有这个对象模型:

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 错误:元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型“更新”。 在 'Update'.ts(7053) 类型上没有找到带有 'string' 类型参数的索引签名

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

【问题讨论】:

  • 需要考虑的一点是,在 forEach 中有 await 可能会导致问题,因为 foreach 将立即解决并且代码不会等待。将Promise.all(yourforeach) 包裹起来以确保所有承诺都得到解决是一种很好的做法。实际上,我什至不确定您是否需要在这里等待,因为我没有足够的上下文,

标签: node.js typescript object interface


【解决方案1】:

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

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

确保在使用as const时不要向变量添加类型定义。

【讨论】:

    【解决方案2】:

    这是为了更好地适应 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);
      }));
    }
    

    【讨论】:

    • 我认为这不是一个好的解决方案,因为您的 fieldsfield 仍然键入包含任意字符串。
    • @MaxYankov 你是对的。修改了类型以考虑到这一点:) 不错
    【解决方案3】:

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

    为了正确实现这一点,我将使用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)
            })
    
    }
    

    【讨论】:

      猜你喜欢
      • 2021-11-09
      • 2020-08-10
      • 2023-01-05
      • 1970-01-01
      • 2019-04-29
      • 1970-01-01
      • 2019-07-30
      • 2013-01-26
      相关资源
      最近更新 更多