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

Error: Namespace declaration does not have a type annotation - TypeScript/Babel

After creating my app using the command npx create-react-app --typescript, I encountered an issue with generated code and namespaces causing Babel to throw an error. Here are the steps I took to try and resolve the issue: I ejected the project Updated b ...

Tips for referencing functions in TypeScript code

In regard to the function getCards, how can a type be declared for the input of memoize? The input is a reference to a function. import memoize from "fast-memoize"; function getCards<T>( filterBy: string, CardsList: T[] = CardsJSON.map((item, i ...

Error in ReactJS VSCode while integrating Cypress testing: The name 'cy' cannot be found

Currently working on a ReactJS Typescript project using NPM and VSCode. Despite all my Cypress tests running smoothly, I am encountering a syntax error in VSCode: Error: Cannot find name 'cy' Any ideas on how to resolve this issue? Attempted th ...

Firebase Function deployment encountered an issue during the build phase, despite the predeploy process

My react.js project includes Firebase functions that are configured in a sub-folder called root/functions. These functions are written in typescript and have paths option set in tsconfig.json. In my functions/index.ts file, I import files from various loca ...

io-ts: Defining mandatory and optional keys within an object using a literal union

I am currently in the process of defining a new codec using io-ts. Once completed, I want the structure to resemble the following: type General = unknown; type SupportedEnv = 'required' | 'optional' type Supported = { required: Gene ...

Modifying Data with MomentJS when Saving to Different Variable

After attempting to assign a moment to a new variable, I noticed that the value changes on its own without any modification from my end. Despite various attempts such as forcing the use of UTC and adjusting timezones, the value continues to change unexpec ...

How can you generate a distinct id value for each element within an ngFor iteration in Angular 4?

I encountered an issue where I must assign a distinct id value to each data row within my *ngFor loop in angular 4. Here is the code snippet: <div *ngFor="let row of myDataList"> <div id="thisNeedsToBeUnique">{{ row.myValue }}</div> & ...

What is the best way to access the original observed node using MutationObserver when the subtree option is set to

Is there a way to access the original target node when using MutationObserver with options set to childList: true and subtree: true? According to the documentation on MDN, the target node changes to the mutated node during callbacks, but I want to always ...

Exploring TypeScript Generics and the Concept of Function Overloading

How can I create a factory function that returns another function and accepts either one or two generic types (R and an optional P) in TypeScript? If only one generic type is provided, the factory function should return a function with the shape () => ...

Encountering a hiccup while trying to install Svelte, Skeleton, and Tail

Recently entering the world of Svelte and TypeScript, I have encountered some unexpected errors after installation. Despite following the same steps as before, I am puzzled by what is causing these issues. This is the process I followed: npm create svelte ...

The best practices for utilizing ES6 Modules syntax in TypeScript files within a NextJS environment

The issue appears to be trapped in a loop: package.json is missing type: "module". This results in an error when trying to use modules in TypeScript files: An error occurred while running the seed command: /Users/me/code/me/prisma-learning/grap ...

Retrieve a collection of Firebase records using a specific query parameter

I'm currently developing a web app with Angular 2 and facing an issue with retrieving data from Firebase based on specific conditions in the child node. Here's how my Firebase structure looks like: I need to extract the entry for the one with app ...

Touch gestures using Hammer.js including tapping and swiping downwards

Is there a way to use HammerJS in Angular Material to implement drag-down functionality that triggers an event? I want the dragdown event, as shown in the image below on the gray bar just above the Facebook button. How can I achieve this? ...

Retrieving Headers from a POST Response

Currently, I am utilizing http.post to make a call to a .NET Core Web API. One issue I am facing is the need to extract a specific header value from the HTTP response object - specifically, the bearer token. Is there a method that allows me to achieve thi ...

Tips for generating a subject in rx.js while utilizing 2 parameters

Within my Angular2 application, I am utilizing a communication service to handle interactions between components. When calling the method: this.notification.create('test'); The service structure is as follows: export class NotificationServic ...

Encountering a Javascript error while trying to optimize bundling operations

After bundling my JavaScript with the .net setting BundleTable.EnableOptimizations = true;, I've encountered a peculiar issue. Here's the snippet of the generated code causing the error (simplified): var somVar = new b({ searchUrl: "/so ...

Issue with Typescript and eslint errors occurring exclusively in fresh code - Anticipated a colon.ts(1005)

Lately, in my extensive react-typescript project, I have encountered a peculiar issue. It seems that syntax errors are popping up everywhere, but only within the new code that I write. For instance, when creating a new component: import React from 're ...

Error: Unable to iterate through posts due to a TypeError in next.js

Hi there, this is my first time asking for help here. I'm working on a simple app using Next.js and ran into an issue while following a tutorial: Unhandled Runtime Error TypeError: posts.map is not a function Source pages\posts\index.tsx (1 ...

What are some strategies for circumventing the need for two switches?

My LayerEditor class consists of two private methods: export class LayerEditor { public layerManager: LayerManager; constructor() { this.layerManager = new LayerManager(this); } private executeCommand() { ...

Error: Unable to locate the specified Typescript function

For the source code, please visit https://github.com/zevrant/screeps I am encountering an issue with my implementation of interfaces in TypeScript. When trying to call the implemented interface, I am getting the following error: "TypeError: spawn.memory.t ...