Alert in Typescript when spreading keys that are not required

Can someone explain why I am getting a compiler warning from Typescript when attempting to create a new object based on an existing object of the same type?

In the snippet below, spreading the key2 value results in the error message

Type 'string | undefined' is not assignable to type 'string'.
. Even though key2 is optional, I am spreading the value from object1 which we know contains a key2 entry.

type Test = {
  key1: string;
  key2?: {
    key3: string;
  }
}

const object1:Test = {
  key1: "hello",
  key2: {
    key3: "hi"
  }
}

const object2:Test = {
  ...object1,
  key2: { // error here
    ...object1.key2
  }
}

Type error:

Type '{ key3?: string | undefined; }' is not assignable to type '{ key3: string; }'.
  Types of property 'key3' are incompatible.
    Type 'string | undefined' is not assignable to type 'string'.
      Type 'undefined' is not assignable to type 'string'.(2322)

I am seeking to understand this behavior and the best approach to address such situations.

TS Playground link: https://www.typescriptlang.org/play?#code/C4TwDgpgBAKhDOwoF4oG8BQUoGsIgEYAuKRAJwEsA7AcwG4td8AmAfhM22zxAGYTy1eowC+GMRgDGAeyqIo0gEYArCJODE481JyaESAIgAWEADanpBgDSMezDo275+UYxQOjxGKbPlLV6vZaSDqMAHQR-moaNk4g9uiOUBFhUeoEYXaeIkA

Appreciate your insights

Answer №1

Identifying the data type of key2 yields:

key2?: {
  key3: string;
}

This implies that key2 can be:

  • Absent
  • Undefined
  • { key3: string } (an object with a property key3, which is a string)

What's not permissible, however, is an object containing an optional key3 property.

Upon examining your spread operator's type:

const a = { ...object1.key2 }
// { key3?: string | undefined; }

It's not valid to assign the key2 property in this manner since if it's an object, it must also include a key3 property with a value of type string.


To adhere to this interface, you should avoid creating an object when key2 is undefined.

One approach to achieving this would be:

const object2:Test = {
  ...object1,
  key2: object1.key2 && {
    ...object1.key2
  }
}

Playground

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

Issue with push notifications on Ionic 2 specifically for Android 4 devices

Currently, I am working on a project that involves push notifications using the IONIC NATIVE PLUGIN. Everything works smoothly when running ionic cordova run android on android version 5. However, when trying to run it on android version 4, I encounter an ...

Enhance ES6 Promises with TypeScript overrides using Bluebird

I am encountering a challenge with a Node.js library that utilizes promises, specifically TypeScript declarations using ES6 Promise. Interestingly, this library can be adjusted to work with any promise library, such as Bluebird. The issue lies in making t ...

Efficient ways to exchange data at the application level across pages in Angular 2 and higher versions

Throughout my experience with various Angular projects, I have encountered the challenge of effectively sharing application-level data between different pages. There are several methods to tackle this issue, such as using a service and injecting it into p ...

automatic sign out due to inactivity in an Aurelia application

Here's a quick summary: How can I trigger a function inside a view-model from outside of it using Aurelia? I want to automatically log out a user if they remain inactive for a certain amount of time without performing any actions. After reading throu ...

What exactly occurs when a "variable is declared but its value is never read" situation arises?

I encountered the same warning multiple times while implementing this particular pattern. function test() { let value: number = 0 // The warning occurs at this line: value is declared but its value is never read value = 2 return false } My curi ...

What is the method for converting a JSON string into an [object][object] format using Angular 6?

Is there a way to transform the data shown below into the [[object][object]] structure using Angular 6? resultArray = [{Q_id: "5bbee2fbbb34b98be0464c73", opt_id: 111},{Q_id: "5bbee2fbbb34b98be0464c73", opt_id: 113}] ...

What is the best approach for iterating through the data that I obtain from an API?

When attempting to iterate through data fetched via an API, I encountered the following error message: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays ...

Images are failing to render on Next.js

Hello there! I am facing an issue while working on my Next.js + TypeScript application. I need to ensure that all the images in the array passed through props are displayed. My initial approach was to pass the path and retrieve the image directly from the ...

What is the best way to explain to Typescript how to interpret a factory function that generates variable class definitions?

In my current project, I am utilizing Angular v16 and ngxs v18.0 simultaneously. The project consists of multiple grids that require a similar set of actions. To streamline this process, we attempted to create a factory function that would generate action ...

What is the appropriate return type for this function in TypeScript?

Seeking clarity on a fundamental TypeScript concept here. I've noticed that Google Cloud examples use JavaScript, and I'm in the process of converting one to TypeScript. Source: https://cloud.google.com/storage/docs/listing-buckets#storage-list ...

Need to end all Node.js instances to properly reflect the code. Any solutions for resolving this issue?

After developing an application using typescript, hapi, and nodejs, I encountered a strange issue. Whenever I save, remove, or add new code, the changes are not reflected even after running gulp build. The only way to get it working is by closing all run ...

Exploring Angular's APP_INITIALIZER: Comparing Promises and Observables

I have implemented an Angular v4 application where I need to retrieve settings from the server before the app starts. This is achieved using the APP_INITIALIZER: { provide: APP_INITIALIZER, useFactory: initializeSettings, deps: [SettingsService], ...

How can I update a property within an object in a sequential manner, similar to taking turns in a game, using React.js?

I am currently working on a ReactJs project where I am creating a game, but I have encountered an issue. I need to alternate turns between players and generate a random number between 1 and 10 for each player, storing this random number inside their respec ...

how to make a "select all" checkbox with Angular 2

`I'm currently working on a feature that allows a checkbox to select all checkboxes within a specific div when checked. The div exclusively contains checkboxes. //TS FILE constructor() { } checkAll: ElementRef | undefined; selectAll(isChecked: ...

TypeScript type for a universal filter system

One's generic repository interface includes: type RecursivePartial<T> = { [P in keyof T]?: T[P] extends (infer U)[] ? RecursivePartial<U>[] : T[P] extends object ? RecursivePartial<T[P]> : T[P]; }; interface Repository ...

A guide on printing several PDF files at once with print.js in Angular 9

After successfully using the print.js library to print a single PDF, I encountered an issue when attempting to print multiple PDFs. An error message stating "ERROR Multiple Choices" was displayed. I also experimented with plain JS, but it resulted in multi ...

Having numerous repetitions of identical modals in Ionic 2/3

My app.component contains a background mode service that shares data via intent to a behavior Subject. this._notification.setNotiService2(data.extras); After logging in, the root is set to TabsPage. this.appCtrl.getRootNav().setRoot('TabsPage' ...

Tips on ensuring that the effect only impacts the modified component

I'm facing an issue where two input components show changes simultaneously. How can I display only the changed input component? input.tsx export const Input: React.FC<InputProps> = ({ type, placeholder, classNameProp, value, onChange, forwardRe ...

atom-typescript - What could be causing the unrecognized Typescript configuration options?

I'm puzzled as to why I am encountering the errors depicted in the screenshot below. Atom is indicating that my tsconfig.json file has 'project file contains invalid options' for allowJs, buildOnSave, and compileOnSave. However, according ...

Angular - Customizing button bindings for various functions

As a newcomer to Angular and TypeScript, I am faced with the task of creating a customizable button that can display text, an icon, or both. For example: button-icon-text-component.html <button> TEST BUTTON </button> app.component.html & ...