Reputation: 183
I have a function trying to return an object it receives with the keys all Pascal case instead of Camel case.
My Interfaces:
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;
}
My Code:
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;
}, {});
Typescript is giving me the following error message:
Type '{}' is missing the following properties from type 'INodeMailerResponseUpper': Accepted, Rejected, EnvelopeTime, MessageTime, and 3 more.ts(2740)
Question: How do I correctly type my accumulator when doing the reduce?
Upvotes: 1
Views: 1482
Reputation: 14148
Use Partial<INodeMailerResponseUpper>
for the reduce
type parameter. This will mean acc
has that type and will allow you to assign properties to it. However, you need to cast the result to INodeMailerResponseUpper
because TypeScript doesn’t know that the final result will contain all the required properties.
You could do it like this, which uses a fair bit of type assertions:
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;
Or you could also improve the type of lodash’s upperFirst
(using 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;
Unfortunately, there isn’t a way to completely avoid type assertions.
Upvotes: 2