Guide on enabling a new property within an Interface containing a nested array

Within my interface, there is a property named data which contains an array. The structure looks like this:

type Data = { prop1: string; prop2: string }[]; 

interface MyInterface {
  prop1: string;
  data: Data;
}

Now, I have an RxJS stream where the type is MyInterface.

I want to modify the data property slightly by adding a new value.

type DataExtended = Data & {
  newValue: string
}

This new type is added to an extended interface.

interface MyInterfaceExtended extends MyInterface {
  data: DataExtended
}

In the controller, I invoke a service that expects an HTTP result of type MyInterface. However, I need to alter the data structure as follows:

var myData$ = Observable<MyInterfaceExtended>;

constructor(private myService:myservice){
  this.myData$ = this.myService.get().pipe((map(value)) => {
      foreach(value.data,  (data) =>{
        data.newValue = 'new';
      })
      return value
  })
}

Despite this setup, I am encountering an error stating:

'newValue' does not exist on type {etc}

What could be causing this issue?

Answer №1

Premise:

Let's assume that the this.myService.get() function returns Observable<MyInterface>.

An issue arises with the DataExtended type when combining the array of Data, which consists of { prop1: string; prop2: string }, with an object { newValue: string }.

The correct type should be as follows:

type DataExtended = Data &
  {
    newValue: string;
  }[];

for existing data types.

Alternatively, you can define the Data as a single object instead of an array type.

New data types:

type Data = { prop1: string; prop2: string };

interface MyInterface {
  prop1: string;
  data: Data[];
}

type DataExtended = Data &
  {
    newValue: string;
  };

interface MyInterfaceExtended extends MyInterface {
  data: DataExtended[];
}

To convert the data using the RxJS operator map, you can use the following solutions:

Existing data types - Solution 1:

this.myData$ = this.myService.get()
  .pipe(
    map((response: any) => {
      let newResponse: MyInterfaceExtended = response;

      newResponse.data = newResponse.data.map((x) => ({
        ...x,
        newValue: 'new',
      }));

      return newResponse;
    })
  );

New data types - Solution 2:

this.myData$ = this.myService.get()
  .pipe(
    map(
      (response: any) =>
        ({
          data: response.data.map(
            (x: Data) =>
              ({
                ...x,
                newValue: 'new',
              } as DataExtended)
          ),
        } as MyInterfaceExtended)
    )
  );

Demo @ StackBlitz

Answer №2

Learn how to design universal interfaces.



interface BasicUserDetails<ID = number> {
  id: ID;
  firstName: string;
  lastName: string;
}

interface UserWithContacts extends BasicUserDetails<number> {
  phone: string;
}

interface CustomUser<UserDetail> {
  details: UserDetail;
}

const basicUser: CustomUser<BasicUserDetails> = {
  details: {
    id: 1,
    firstName: 'John',
    lastName: 'Doe',
  },
};

const userWithContact: CustomUser<UserWithContacts> = {
  details: {
    id: 1,
    firstName: 'Jane',
    lastName: 'Smith',
    phone: '123-456-7890',
  },
};




A Different Scenario



interface BaseEntity<Identity> {
  id: Identity;
}

interface SelectFieldByID<Type, Key extends keyof Type = keyof Type> {
  idKey: Key;
}

interface UserEntityData
  extends BaseEntity<number>,
    SelectFieldByID<UserEntityData, 'uuid' | 'username'> {
  uuid: string;
  username: string;
  password: string;
}



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

Declaring global types in a NX and NextJS monorepository for enhanced development consistency

I've been searching online to find a good solution for my issue, but so far I haven't had any luck. Currently, I have a NX monorepo with NextJS and I'm attempting to create a global types/ folder that can be accessed by all my apps and libs ...

Utilizing a service within NestJS

I'm currently in the process of updating some older code and I have created a service that I want to inject into the constructor of a class. There are two key points to consider about this particular class. The first point is that it is instantiated b ...

Is it possible to implement a different termination condition when using *ngFor in Angular 2?

After countless hours of searching on Google, I have yet to discover a method for implementing an alternative stop condition for loops created with the *ngFor directive. By default, *ngFor loops end with this condition: index < array.length. Is there a ...

Angular keeping track of the variable data with each click event

Recently diving into angular, I have a scenario where each table row (tr) has a click event to trigger an expand/collapse functionality displaying data below it. The issue arises when clicking on a new tr triggers the API call and updates every expanded tr ...

I encountered a TS error warning about a possible null value, despite already confirming that the value

In line 5 of the script, TypeScript raises an issue regarding the possibility of gameInstanceContext.gameInstance being null. Interestingly, this concern is not present in line 3. Given that I have verified its existence on line 1, it is perplexing as to w ...

Angular checkboxes not updating with current values when submitted

I have defined a static array in TypeScript like this: permissions: any[] = [ { permission: "Read", enabled: true }, { permission: "Write", enabled: false }, { permission: "Delete", enabled: false }, { permission: "Edit", enabled: true } ...

Error in NextJS with TypeScript when updating data in a useState variable

Recently, I started working with TypeScript, ReactJS, and NextJS, but I encountered a TypeScript error that I need help fixing. My current project involves using NextJS 14, server actions, and Prisma as the ORM for a university-related project. An issue ar ...

Guide on setting up factories with pre-existing relationships in MIKRO-ORM

Hey there! I'm currently exploring how to set up a factory and establish relationships between models. For instance, I have a UserFactory that corresponds to the User entity which is connected to the userType table. However, in the factory, I'm ...

Vite: What steps can be taken to verify the TypeScript configuration of a React application when typechecking suddenly fails across the entire project?

My React application, built with Vite and TypeScript, is experiencing a breakdown in typechecking. I have not been able to locate a previous state in the commits where it was functioning properly. For instance, I am encountering errors like: Cannot find ...

Modify just one feature of ReplaySubject

I am currently working with a ReplaySubject containing user details of type UserDetails. userData: ReplaySubject<UserDetails>; The UserDetails class includes the following properties, two of which are optional: export class UserDetails { name: ...

Tips on how to modify the session type in session callback within Next-auth while utilizing Typescript

With my typescript setup, my file named [...next-auth].tsx is structured as follows: import NextAuth, { Awaitable, Session, User } from "next-auth"; // import GithubProvider from "next-auth/providers/github"; import GoogleProvider from ...

Tips on rotating a material-ui icon

Having trouble rotating a material-ui icon using the CSS animation property. Can anyone assist in identifying what may be causing the issue? Link to example code sandbox I'm looking for a continuously rotating icon. ...

Evolution of Angular: Migrating from Angular 1 to Angular 5 with Nested Component

In the past Angular 1.5 ui-router Presently Angular 5.0 Is it possible to import subcomponents in a parent component similar to Angular 1.5? I followed the Heroes tutorial for Angular 5, but it did not cover this transition as all components are impo ...

Remove Fragment in Angular Routing after navigating to a different route

I am trying to figure out how to remove an Angular route fragment after I have already navigated to the Route+Fragment. Currently, the route fragment, which is part of the navigated URL, is causing an issue for users who have scrolled to a different sectio ...

Utilize ngFor within a ng-template to display dynamic content in a table structure

Currently, I am attempting to loop through a list that is obtained from an API request and then populate the data into a table. The issue I am facing is that this table exists within an ng-template tag, and I am unsure of how to manage this situation. Thi ...

Rule of authentication using Firebase Database

I need to establish a rule in my Firebase Database to prevent unauthorized access for reading and writing purposes. Within my database, there is a collection of words, each containing a "uid" field that corresponds with the uid of the authUser key stored ...

Array of React components with covariant types

I have a custom class that extends a base class and combines the properties of both. Here is an example: interface BaseFooProps { name: string; } type BaseFoo<T extends BaseFooProps = BaseFooProps> = React.FC<T & BaseFooProps>; const Base ...

Exploring the depths: Retrieving nested object attributes using ngFor

Trying to display the "type" value in the ngFor table resulted in receiving object '[object Object]' of type 'object.' NgFor only supports binding to Iterables such as Arrays. json [{ "id": 123, "name": "Paul", "cars": { ...

Filtering in RxJS pipelines can be compared to an if-else statement

I'm not very familiar with JS and RxJS, so please pardon me if my question seems trivial. Here is a code snippet that I didn't write: prepare(): Observable<any> { const i = of({}).pipe( // Check if file type is image fil ...

Angular 5 project encounters a 404 error while attempting to send a delete request to a .net web API

Whenever I try to send a delete request from my Angular 5 app to the .NET Web API, I receive a "DELETE http://localhost:51352/api/Account/undefined 404 (Not Found)" error. Below is the code snippet from my user.component.ts file in Angular: delete(id){ ...