首页 > 解决方案 > 在对象上使用 reduce 时的类型问题

问题描述

我有一个函数试图返回一个对象,它使用所有 Pascal 大小写而不是 Camel 大小写的键接收。

我的接口:

export interface INodeMailerResponseLower {
    accepted: string[];
    rejected: string[];
    envelopeTime: number;
    messageTime: number;
    messageSize: number;
    response: string;
    messageId: string;
}

export interface INodeMailerResponseUpper {
    Accepted: string[];
    Rejected: string[];
    EnvelopeTime: number;
    MessageTime: number;
    MessageSize: number;
    Response: string;
    MessageId: string;
}

我的代码:

import { upperFirst } from 'lodash';

const response: INodeMailerResponseLower;   // << insert object values here
const formattedResponse: INodeMailerResponseUpper = Object.keys(response).reduce((acc, key) => {
     acc[upperFirst(key)] = response[key];
     return acc;
   }, {});

打字稿给我以下错误信息:

类型“{}”缺少类型“INodeMailerResponseUpper”中的以下属性:Accepted、Rejected、EnvelopeTime、MessageTime 和 3 个以上。ts(2740)

问题: 在做 reduce 时如何正确输入我的累加器?

标签: typescript

解决方案


用于类型参数Partial<INodeMailerResponseUpper>reduce这将意味着acc具有该类型,并允许您为其分配属性。但是,您需要将结果转换为,INodeMailerResponseUpper因为 TypeScript 不知道最终结果将包含所有必需的属性。

你可以这样做,它使用了相当多的类型断言:

const formattedResponse = Objectkeys(response)
    .reduce<Partial<INodeMailerResponseUpper>>((acc, key) => {
        (acc[upperFirst(key) as keyof INodeMailerResponseUpper] as unknown) =
            response[key as keyof INodeMailerResponseLower];
        return acc;
    }, {}) as INodeMailerResponseUpper;

或者你也可以改进 lodash 的类型upperFirst(使用 TypeScript 4.1):

declare module 'lodash' {
    interface LoDashStatic {
        upperFirst<S extends string = ''>(string?: S): Capitalize<S>;
    }
}

const formattedResponse = (Object.keys(response) as (keyof INodeMailerResponseLower)[])
    .reduce<Partial<INodeMailerResponseUpper>>((acc, key) => {
        // Without the as unknown, TypeScript would complain that
        // string | number | string[] is not assignable to undefined
        (acc[upperFirst(key)] as unknown) = response[key];
        return acc;
    }, {}) as INodeMailerResponseUpper;

不幸的是,没有办法完全避免类型断言。


推荐阅读