0

I have an interface that has multiple nested objects and I want to have an easier way to initialize them.

currently my interface

export interface Order {
  _id: string;
  orderDetails: {
    create_time: string;
    id: string;
    payer: {
      address: {
        country_code: string;
      };
      email_address: string;
      name: {
        given_name: string;
        surname: string;
      };
      payer_id: string;
    };
    purchase_units: [
      {
        amount: {
          value: string;
          currency_code: string;
        };
        payee: {
          email_address: string;
          merchant_id: string;
        };
        shipping: {
          address: {
            address_line_1: string;
            address_line_2: string;
            admin_area_1: string;
            admin_area_2: string;
            country_code: string;
            postal_code: string;
          },
          name: {
            full_name: string
          }
        };
      }
    ]
  };
  products: [
    {
      quantity: number
      _id: string,
      product: {
        _id: string,
        amount: number,
        category: string,
        description: string,
        imageUrls: [],
        title: string,
        userId: string
      }
    }
  ];
  user: {
    name: string,
    userId: string
  };
}

and then I receive them like this

export class AllOrdersComponent implements OnInit {
  order: Order = {orderDetails: {payer:{name: {} as any}as any} as any} as any;
  id: string;
  constructor(
    private route: ActivatedRoute,
    private adminService: AdminService
  ) {}

  ngOnInit() {
    this.route.params.subscribe((params: Params) => {
      this.id = params["id"];
      this.adminService.getOrder(this.id)
     .subscribe(orderData => {
       this.order = orderData.order;
     })
    });
  }
}

the problem is, if I do not initialize them before doing the http request in the OnInit function then I get an error that '_co.order.orderDetails' is undefined.

so I initialize them as I do at the start of the component, however, it looks very verbose and redundant there must be a prettier and easier way to do this?

1
  • Yes it seems unlikely that this cant be done in a much prettier way, however I dont see _co.order.orderDetails used anywhere. Can you provide a minimal example of your problem, perhaps on stackblitz? Commented Apr 24, 2020 at 11:47

1 Answer 1

3

The problem is not the structure of your object. When you are waiting for an asynchronous data, everywhere you want to use it, you have to check if the variable is defined. Don't make yourself an empty object. Keep it undefined before you get the actual data.

So in you HTML, you may use

<div *ngIf="order">
  <span>{{ order.orderDetails.payer.email_address }}</span>
</div>

Also, while defining your interface, you may create sub-object's interfaces, for lisibility:

export interface Order {
  _id: string;
  orderDetails: OrderDetails;
  products: Products[];
  user: User;
}
Sign up to request clarification or add additional context in comments.

3 Comments

He could also just turn order into an observable and then use the async pipe in the html.
Indeed, with the drawback to not be able to use it outside the HTML then.
That drawback only exists if you can't have user interactions. A simple (click)="someProcessing(order)" would get the order into the ts. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.