Navigating through diverse objects in Typescript

My challenge involves a state object and an update object that will merge with the state object. However, if the update value is null, it should be deleted instead of just combining them using {...a, ...b}.

const obj = {
    other: new Date(),
    num: 5,
    str: "original string"
}

const objUpdate: Partial<typeof obj> = {
    num: 6,
    str: "updated string"
}

The task at hand is to loop through the update object and update the original object accordingly. Ideally, I would approach it like this:

Object.entries(objUpdate).forEach(([k,v]) => {
    if (v === undefined) return;
    if (v === null){
        delete obj[k]; // <-
        return;
    }
    obj[k] = v; // <-
})

However, I encounter an error indicating that

No index signature with a parameter of type 'string' was found on type '{ other: Date; num: number; str: string; }'
. It seems like Typescript needs clarification on the type of k, so I explicitly define it as:

Object.entries(objUpdate).forEach(([k,v]) => {
    if (v === undefined) return;
    if (v === null){
        delete obj[k as keyof typeof objUpdate];
        return;
    }
    obj[k as keyof typeof objUpdate] = v; // <-
})

Now, I face an error stating that

Type 'string | number | Date' is not assignable to type 'never'. Type 'string' is not assignable to type 'never'.

  1. Is there a way to assist Typescript in correctly inferring typings in this scenario?
  2. Is there a more effective method to achieve my goal?

Answer №1

Removing keys dynamically from an object in JavaScript can be slow and cause typing challenges in TypeScript. A more efficient approach would be to adjust other parts of your code that reference the state to check if a value is null. For example, instead of defining a state object like

const obj = {
    other: <someDate>,
    str: <someString>
}

You could define it as

const obj = {
    other: <someDate>,
    num: null,
    str: <someString>
}

This method ensures smooth typing and simplifies state updates using {...a, ...b}.

To set the initial state type, create a new object type with null included for each key.

const obj = {
    other: new Date(),
    num: 5,
    str: "original string"
}
type Obj = typeof obj;
type ObjState = {
  [K in keyof Obj]: Obj[K] | null;
};

// ...

const [stateObj, setStateObj] = useState<ObjState>(obj);
// Update:
setStateObj({ ...stateObj, ...objUpdate });

If certain parts of the code need the object without the null properties (e.g., for a database query), create a new object only when necessary instead of altering the shape of the state.

const objWithNullPropertiesRemoved: Partial<Obj> = Object.fromEntries(
  Object.entries(stateObj)
    .filter(([, val]) => val !== null)
);
// send the objWithNullPropertiesRemoved somewhere

Answer №2

While the answer I initially accepted may be considered the most appropriate for many individuals, I have managed to discover a different method that allows me to execute my original approach successfully. As a result, I am sharing it here to ensure completeness.

After referring to Transform union type to intersection type, I proceeded to define the value v as

as UnionToIntersection<typeof obj[keyof typeof obj]>

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

What is the best way to retrieve data from within a for loop in javascript?

Seeking assistance in Typescript (javascript) to ensure that the code inside the for loop completes execution before returning I have a text box where users input strings, and I'm searching for numbers following '#'. I've created a fun ...

Using useState, react, and typescript, is there a way to set only the icon that has been clicked to

When I click on the FavoriteIcon inside the ExamplesCard, all the icons turn red instead of just the one that was clicked. My approach involves using useState to toggle the icon state value between true and false, as well as manipulating the style to adjus ...

RxJS: the art of triggering and handling errors

This is more of a syntax question rather than a bug I'm facing. The process is straightforward: Send an HTTP request that returns a boolean value If the boolean is true, proceed If the boolean is false, log a warning and stop the flow. To handle ...

What is the best way to create an assertion function for validating a discriminated union type in my code?

I have a union type with discriminated properties: type Status = { tag: "Active", /* other props */ } | { tag: "Inactive", /* other props */ } Currently, I need to execute certain code only when in a specific state: // At some po ...

Is it possible to extract specific columns from the Convex database?

I am looking to retrieve all columns from a table using the following code snippet. Is there a more efficient way to achieve this? I couldn't find any information in the documentation. Does anyone have a workaround or solution? const documents = await ...

What are some methods for retrieving RTK Query data beyond the confines of a component?

In my React Typescript app using RTK Query, I am working on implementing custom selectors. However, I need to fetch data from another endpoint to achieve this: store.dispatch(userApiSlice.endpoints.check.initiate(undefined)) const data = userApiSlice.endpo ...

Tips for monitoring the loading of data in TypeScript with observers?

One of the methods in my class is responsible for fetching information from the server: public getClassesAndSubjects(school: number, whenDate: string) { this.classService.GetClassesAndSubjects(school, whenDate).subscribe(data => { if (!data.h ...

Is there a way to specifically target the MUI paper component within the select style without relying on the SX props?

I have been experimenting with styling the Select MUI component using the styled function. I am looking to create a reusable style and move away from using sx. Despite trying various methods, I am struggling to identify the correct class in order to direct ...

Warning: Typescript is unable to locate the specified module, which may result

When it comes to importing an Icon, the following code is what I am currently using: import Icon from "!svg-react-loader?name=Icon!../images/svg/item-thumbnail.svg" When working in Visual Studio Code 1.25.1, a warning from tslint appears: [ts] Cannot ...

Frontend Angular Posting Data to Server

https://i.sstatic.net/6dcPt.png https://i.sstatic.net/uFMuL.png I have two components - one is a form and the other is a dialog with a form. When I click on the dialog with the form and input data, I want to save it first in an in-memory, and then post all ...

Tips for Resolving TypeScript Error 7053 when using the handleChange function in a React Form

Seeking assistance with creating a versatile handleChange function for a React form. The goal is for the handleChange function to update the state value whenever a form field is modified, while also accommodating nested values. Below is my attempt: const ...

Navigating the complexities of managing numerous checkboxes in React

I am a beginner with react and recently received a task to complete. The requirements are: Show multiple checkboxes. The order of checkbox names may change in the future, allowing the client to decide the display order. Display checkboxes based on their a ...

The ViewChild from NgbModalModule in @ng-bootstrap/ng-bootstrap for Angular 6 is causing the modal to return as

I have successfully integrated ng bootstrap into my project, specifically utilizing the modal module to display a contact form. The form includes input fields for email and message, as well as a submit button. You can find the ngbootstrap module I am using ...

Modify the "field" key type within the GridColDef interface of MUI DataGrid

Is there a way to assign an array of specific strings to the default type of GridColDef's field key, which is typically set to string? I attempted solutions like Array<Omit<GridColDef, 'field'> & {field: 'name' | &apo ...

Angular provides a variety of functionality to control the behavior of elements in your application, including the

I have a page with Play, Pause, Resume, and Stop icons. When I click on the Play icon, the Pause and Stop icons are displayed. Similarly, I would like to show the Resume and Stop icons when I click on the Pause icon. I need help with this code. Thank you. ...

Deploying AWS CDK in a CodePipeline and CodeBuild workflow

I am currently attempting to deploy an AWS CDK application on AWS CodePipeline using CodeBuild actions. While the build and deploy processes run smoothly locally (as expected), encountering an issue when running on CodeBuild where the cdk command fails w ...

Identifying Shifts in Objects Using Angular 5

Is there a way to detect changes in an object connected to a large form? My goal is to display save/cancel buttons at the bottom of the page whenever a user makes changes to the input. One approach I considered was creating a copy of the object and using ...

Error: BrowserModule has already been loaded

After updating my application to RC6, I encountered a persistent error message: zone.js:484 Unhandled Promise rejection: BrowserModule has already been loaded. If you need access to common directives like NgIf and NgFor from a lazily loaded module.. ...

Reusing methods in Javascript to create child instances without causing circular dependencies

abstract class Fruit { private children: Fruit[] = []; addChild(child: Fruit) { this.children.push(child); } } // Separate files for each subclass // apple.ts class Apple extends Fruit { } // banana.ts class Banana extends Fruit { } ...

Utilizing Prisma Enum with Nest JS: A Comprehensive Guide

While working on my backend with Prisma and NestJS, I have encountered an issue. I defined an enum in Prisma that works fine in debug mode, but when I generate the Prisma client using nest build, I get an error. Object.values(client_1.RoomSharingType).join ...