[Fixed] Angular/TS: how to get the values of properties from partial extended interface?

Issue

Very new to Angular/TS and maybe I have phrased this wrong but I will try to explain as best I can.

I have 2 interfaces, one extends the other like this:

export interface CustomerModel {
   firstName: string;
   lastName: string;
    //other things
}

export interface OrderModel extends Pick<CustomerModel, 'firstName' | 'lastName' {
  orderNumber: number;
}

I have created a service with a hardcoded instance of Customer (working local on machine and for now everything is hardcoded. I will eventually work with DB but I need this to work this way first)

export class CustomerService {
  customers: CustomerModel[];
  constructor() {
    this.customers = [{
     firstName: 'John',
     lastName: 'Doe',
    //more here 
       },
{
     firstName: 'Jane',
     lastName: 'Smith',
    //more here 
       },
     ]
   }

   getCustomers(): Observable<CustomerModel[]> {
    const customers = of(customers);
    return customers;
 }
}

Now I am trying to create an Order Service using the OrderModel

export class OrderService {
  orders: OrderModel[];
  constructor() {
    this.orders = [{
     orderNumber: 123;
     firstName: ???, //what do I put here to pick up the name from CustomerModel
     lastName: ???,
       },
     { 
    //more here 
       },
     ]
   }

   getOrders(): Observable<OrderModel[]> {
    const orders = of(orders);
    return orders;
 }
}

When I hover over the value of firstName in my orderservice, it does say it is from CustomerModel so I know that the extended worked.
If I leave firstName and lastName out of the orders array, I get an error saying that OrderModel is expecting them.
Maybe this is not possible and there is possibly a better solution but I have been going round in circle trying to see if this works.
Can anyone help me get the value of the property firstName/lastName from the CustomerModel?

Solution

Your best bet in this case is to have a separate file that holds all the base data for the user, and then transform that to whatever you need later.

// app/some-folder/customers.ts
export const customers: CustomerModel[] = [
  {
    firstName: 'John',
    lastName: 'Doe',
    //more here 
  },
  {
    firstName: 'Jane',
    lastName: 'Smith',
    //more here 
  },
];

And in the service

import { customers } from '@app/some-folder/customers.ts'

export class CustomerService {

  public getCustomers(): Observable<CustomerModel[]> {
    return of(customers);
  }

}
import { customers } from '@app/some-folder/customers.ts'

// map the existing customers, and transform it to also have an orderNumber
// use ...a, orderNumber: i to merge the whole customer add orderNumber together
const orders: OrderModel[] = customers.map((a, i) => ({
  firstName: a.firstName,
  lastName: a.lastName,
  orderNumber: i,
}))

// or you can do this, which is more in-line with how an API would respond
// generally an order would just include the customerId, or have a customer object
// const orders = customers.map((a, i) => ({ customer: a, orderNumber: i }))


export class OrderService {

  public getOrders(): Observable<OrderModel[]> {
    return of(orders);
  }

}

This way when you implement the API, all you have to do is swap out the bodies of your functions.

Leave a Reply

(*) Required, Your email will not be published