Challenges arise when employing reduce with data types in an object

I want to transform an object in a function so that all keys are converted from Camel case to Pascal case.

My Declaration:

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 Implementation:

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;
   }, {});

An Error Occured:

Type '{}' is missing the following properties from type 'INodeMailerResponseUpper': Accepted, Rejected, EnvelopeTime, MessageTime, and 3 more.ts(2740)

Inquiry: How can I correctly define the type for my accumulator when using reduce method?

Answer №1

When using the

Partial<INodeMailerResponseUpper>
for the reduce type parameter, you can ensure that acc has the correct type to assign properties to it. However, a cast to INodeMailerResponseUpper is necessary because TypeScript may not recognize that the final result will contain all required properties.

One way to achieve this is through multiple type assertions, as shown in the following example:

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

Alternatively, you can enhance the type of lodash’s upperFirst function by declaring it in 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) => {
        // Using `as unknown` here avoids potential complaints from TypeScript
        (acc[upperFirst(key)] as unknown) = response[key];
        return acc;
    }, {}) as INodeMailerResponseUpper;

It's worth noting that some level of type assertion may still be necessary in these scenarios.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Does the routing in Angular 2 get disrupted by parameter breaks in sub-modules?

In my Angular 2 application, I am encountering an issue with routing to my line module. Currently, I have two submodules - login and line. The routing to the login submodule is working well. However, when I attempt to route to the line module with route pa ...

Launching a new tab with a specific URL using React

I'm attempting to create a function that opens a new tab with the URL stored in item.url. The issue is, the item.url property is provided by the client, not by me. Therefore, I can't guarantee whether it begins with https:// or http://. For insta ...

Experiencing an error message stating 'The token ${Token[TOKEN.72]} is invalid' while using cdk synth, specifically when trying to assign the value of ec2.Vpc.cidr from cfnParameter.value

Attempting to utilize the AWS CDK CfnParameter to parameterize the CIDR value of ec2.Vpc. The aim is to make the stack reusable for VPC creation with the CIDR as a customizable value. An error stating "${Token[TOKEN.72]} is not valid" occurs during synthe ...

Broaden your interfaces by implementing multiple interfaces with Zod

Utilizing typescript, I am able to incorporate multiple interfaces interface Name { name: string } interface Age { age: number } interface People extends Name, Age { height: number } Is there a similar way to achieve this with Zod? What I attempted ...

Swapping out 'useResult' in graphql for Vue and Apollo: A step-by-step guide

I need to replace the useResult function that is fetching data from GraphQL with a computed function. const locationOptions = useResult( result, [], ({ getLocations }): Option[] => formatOptions(getLocations) ) Instead, I want ...

Achieving CommonJS imports compilation with Typescript

In my TS file, I've included a 3rd party package using import XXX { YYY, ABC, 123 } from 'XXX'; While it compiles to CommonJS without any issues, I'd prefer to have it compiled to an ESModule instead. I tried changing the target and mo ...

Find the calculated values within an Angular Material table

I came across this fantastic example of an Angular Material table with checkboxes that fits perfectly with what I want to implement in my application. However, I am facing a challenge - I need to calculate the total value of the checked rows. Specifically, ...

Creating a new list by grouping elements from an existing list

I have successfully received data from my API in the following format: [ {grade: "Grade A", id: 1, ifsGrade: "A1XX", ifsType: "01XX", points: 22, type: "Type_1"}, {grade: "Grade B", id: 2, ifsGrade: &quo ...

Looking to retrieve the AssetLoadedFunc properties in the LoadAssets function? Wondering if you should use TypeScript or JavaScript

When I invoke this.AssetLoadedFunc within the function LoadAssets(callback, user_data) LoadAssets(callback, user_data) { this.glg.LoadWidgetFromURL("assets/Js/scrollbar_h.g", null, this.AssetLoaded, { name: "scrollb ...

Guide to making a TreeView in Angular 2 with Typescript

How can I implement a TreeView in Angular 2 using Typescript? I have searched on Google but have not found any working examples, etc. Could someone kindly provide me with an example to help me accomplish this task? ...

The canDeactivate function in the Angular 2 router can modify the router state even if I choose to cancel an action in the confirmation popup

In my Angular 2 project, I have implemented the canDeactivate method to prevent browser navigation. When a user tries to leave the page, a confirmation popup is displayed. However, if the user chooses to cancel, the router still changes its state even th ...

Using JavaScript library xterm.js in an Ionic 3 application

I am currently working on implementing the xterm.js library into my Ionic 3 project. The source code can be found on Github at: https://github.com/aircable/ionic-xterm along with installation instructions. Although I have been able to compile and start th ...

I'm trying to figure out the best way to successfully pass a prop to another component in TypeScript without running into the frustrating issue of not being able to

I have been facing an issue while trying to pass a prop from a custom object I have defined. The structure of the object is as follows: export type CustomObjectType = { data?: DataObject }; export type DataObject = { id: number; name: stri ...

transferring data between components in a software system

I received a response from the server and now I want to pass this response to another component for display. I attempted one method but ended up with undefined results. You can check out how I tried here: how to pass one component service response to other ...

Create a debounced and chunked asynchronous queue system that utilizes streams

As someone who is new to the concept of reactive programming, I find myself wondering if there exists a more elegant approach for creating a debounced chunked async queue. But what exactly is a debounced chunked async queue? While the name might need some ...

How can I integrate a timer into an Angular carousel feature?

I have put together a carousel based on a tutorial I found on a website. Check out the HTML code for my carousel below: <div class="row carousel" (mouseover)="mouseCheck()"> <!-- For the prev control button ...

Enhance your TypeScript arrays using custom object equality functions

I am looking to utilize array functions such as contains and unique, but I want them to compare equality using my custom equals function. For instance: let arr = [{id:1,..//some more},{id:2,..//some more},{id:3,..//some more}] I need the following code ...

No slides will be displayed in Ionic 2 once the workout is completed

Here is the result of the JSONOBJ: In my home.html file, I have ion-card containing a method called navigate(), which is structured as follows: navigate(event, exercise, exercise2, exercise3, exercise4){ this.navCtrl.push(exerciseSlides, { ...

Steps to troubleshoot a simple function that manages asynchronous tasks

Looking to develop a versatile function that can handle async functions, execute them, and catch any errors that may arise. Coming from a javascript background, I initially managed to create a function that did just this. However, my attempt to enhance it ...

Assign a value to a variable using a function in Typescript

Is there a way in typescript to explicitly indicate that a function is responsible for assigning value to a variable? UPDATED CODE Here, the code has been simplified. While getText() ensures that it will never be undefined, this may not hold true in subs ...