Instructions for adding a new property dynamically when updating the draft using immer

When looking at the code snippet below, we encounter an error on line 2 stating

Property 'newProperty' does not exist on type 'WritableDraft<MyObject>'.  TS7053

// data is of type MyObject which until now has only a property myNumber
const payload = produce(data, (draft) => {    
  draft['newProperty'] = 'test';              // Property 'newProperty' does not exist on type 'WritableDraft<MyObject>'.  TS7053
});                                           

Is there a way to dynamically add a new property to the draft or modify the type of the draft to one that already includes the newProperty? I prefer not to alter the MyObject type to include newProperty.

Answer №1

To maintain the new data type in payload, you must cast the new type on the data parameter:

let payload = produce(data as MyObject & { newProperty: string }, (draft) => {
  draft["newProperty"] = "test";
})

If preserving the type of payload is not a concern, you have the option to change the type of draft either in the function parameter or internally like this:

(draft as MyObject & { newProperty: string })[newProperty] = "test"

Answer №2

It's perfectly acceptable to generate a new object from the produce method as long as you refrain from making changes to the draft object at the same time. The documentation on implementing new data from producers presents a scenario involving a switch statement where some cases alter the draft object while others return a fresh state. This approach is permissible provided that you avoid mixing both actions within a single case.

const payload = produce(data, (draft) => {
    return { ...draft, newProperty: "test" };
});

const n = payload.myNumber; // number
const s = payload.newProperty; // string

Advantages:

  • No need for as assertions
  • payload receives the correct type
    { newProperty: string; myNumber: number; }

Disadvantages:

  • Fails to fully exploit Immer's capabilities

Typescript Playground Link

Answer №3

To extend preexisting types with new properties, you can use the union operator: &. The example code provided below should help address your issue.

(draft: WritableDraft<MyObject> & { newProperty : string }) => {
  // Add your additional code here
}

Modification

Upon reviewing Linda Paiste's response, I have identified some shortcomings in my initial approach. While my solution successfully adds a property to the type, it may lead to increased verbosity and complexity in maintaining the code if type or variable names are altered in the future. Furthermore, it mandates that the function caller provide an object containing the newProperty, which may not be the intended behavior.

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

Set the values retrieved from the http get response as variables in an Angular application

Lately, I've been working on a settings application with slide toggles. Currently, I have set up local storage to store the toggle state. However, I now want to update the toggle status based on the server response. The goal is to toggle buttons accor ...

Is it possible to iterate through TypeScript using both keys and indexes?

Explained in detail at this link, TypeScript introduces a foreach loop: let someArray = [9, 2, 5]; for (let item of someArray) { console.log(item); // 9,2,5 } However, is there a way to access the index/key? I was thinking something along the lines of ...

Sticky header in React data grid

Is there a way to implement a sticky header for a data grid in react? I have tried various methods but haven't been able to figure it out. Any suggestions would be appreciated. You can find my code sandbox example here. #react code export const Styl ...

This phrase cannot be invoked

My code seems correct for functionality, but I am encountering an error in my component that I do not know how to resolve. Can someone please help me with this issue? This expression is not callable. Not all constituents of type 'string | ((sectionNa ...

Challenges encountered while implementing generic types in TypeScript and React (including context provider, union types, and intersection

I have a fully functional example available at this link: The code is working properly, but TypeScript is showing some errors. Unfortunately, I've run out of ideas on how to make the code type safe. I've searched extensively for examples that ma ...

In TypeScript, this regular expression dialect does not permit the use of category shorthand

Recently, I attempted to implement a regular expression in TypeScript: I ran the following code: const pass = /^[\pL\pM\pN_-]+$/u.test(control.value) || !control.value; To my surprise, an error occurred: "Category shorthand not allowed in ...

Navigational menu routing with AngularJS2 using router link paths

Currently, I am working on developing a navigation menu using angularJS2. Here is the snippet from my app.component.ts: import {provide, Component} from 'angular2/core'; import {APP_BASE_HREF, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, HashLocati ...

I'm encountering an error while trying to build my Ag-Grid using npm run build, can someone help me figure out

Being relatively new to Next.js and web development in general, my background mainly consists of working with compiled languages. I recently embarked on a project to build a web app using Ag-Grid, drawing inspiration from an example I found on a public Git ...

The attribute 'location' is not found in the 'File' data type

Recently, I made the switch from using multer to multer-s3 in my project. I have updated the controllers accordingly to store the "location" instead of the "filename". However, I am encountering a typescript error. At the moment, I am utilizing Localstack ...

Issue with ngFor displaying only the second item in the array

There are supposed to be two editable input fields for each section, with corresponding data. However, only the second JSON from the sample is being displayed in both sections. The JSON in the TypeScript file appears as follows: this.sample = [ { "se ...

What is the correct location for storing .html, .css, and other files in a project involving Typescript, Angular 2, and ASP.Net Core 1.0?

When following a Typescript tutorial to create an ASP.Net Core application (with or without Angular 2), it is recommended to set up a folder called Scripts and use gulp tasks to selectively copy only the .js files to the wwwroot folder during the build pro ...

"TypeScript function returning a boolean value upon completion of a resolved promise

When working on a promise that returns a boolean in TypeScript, I encountered an error message that says: A 'get' accessor must return a value. The code snippet causing the issue is as follows: get tokenValid(): boolean { // Check if curre ...

In Angular 2, I am having trouble reaching the properties of an object nested inside another object

I have a variable named contact. When I used console.log(contact) to display its contents, this is what I got: addresss:[] company:"" emails:[] id:3 internet_calls:[] lat:"10.115730000000001" lng:"76.461445" name:"Diji " phones:[] special_days:[] timesta ...

It is impossible to add a promise's value to an array

When attempting to push values into an array and return them, the console only displays an empty array or shows undefined! The issue seems to be that .then does not properly pass the value to the array. const net = require('net'); const find = re ...

Status:0 was received as the response from URL:null during the REST call made from my iOS Ionic application

I am currently facing an issue with a rest call in my Ionic app. The call works fine on Android devices but encounters problems on iOS devices. Below is the implementation of the rest call in my Ionic service. import { Http } from '@angular/http&apos ...

The combination of TypeScript output is not working as expected

Here is my current configuration: tsconfig.json { "compileOnSave": true, "compilerOptions": { "module": "none", "outFile": "js/app.js" } } MyApp.Main.ts class Main { constructor() { Utilities.init(this); ...

The parameter type 'never[]' cannot be assigned to the type 'T | (() => T)' in the argument

Is it possible for the useFetch hook to allow any type of array to be used as the data type? hooks/useFetch.ts: const useFetch = <T extends any[]>(dataUrl: string) => { const [data, setData] = useState<T>([]); const [error, setError] = ...

The value of req.headers('Authorization') has not been defined

I'm experiencing difficulty with my code as the token is coming back as undefined. Here is the frontend section: export const fetchUser = async (token: any) => { const res = await axios.post('/user/getuser', { headers ...

Creating new Angular2 Observables - Subscribing to undefined developments

Is it a scoping issue or a problem with how my observables are set up? Can you assist me in figuring it out? To explain my logic: My goal is to first check if the data is available locally before making an http.get request for it. I want to return the loc ...

Monitor the change in values upon pressing the submit button on Angular

I am currently working with an edit form that contains data in the input fields. <ng-form #infoForm="ngForm" novalidate> <div> <label for="firstName">First Name :</label> <input type=" ...