Home > Enterprise >  How can you create a parent/base interface who's extensions/children can only be used?
How can you create a parent/base interface who's extensions/children can only be used?

Time:01-10

Say I have a DeliveryMethod interface

interface DeliveryMethod {
    specialInstructions: string;
}

Which is used in an Order object to specify how that order will be delivered.

class Order {
  …
  public delivery: DeliveryMethod;
}

At the moment I have two types of delivery methods; in-store pickup

interface InStorePickup extends DeliveryMethod {
  store: DocumentReference;
  carrier: DocumentReference;
  authorisedContacts: {
    firstName: string;
    lastName: string;
    phone: string;
    email: string;
  }[];
}

and shipment

interface Shipment extends DeliveryMethod {
  articleId?: string;
  carrier: DocumentReference;
  recipientDetails: { … }
}

An Order object should only able to be created with an extention/child of DeliveryMethod (such as InStorePickup or Shipment) but not the DeliveryMethod base/parent interface.

This could accomplish this with a union type like so:

class Order {
  …
  public delivery: InStorePickup | Shipment;
}

However, if a new delivery method was introduced in the future (e.g. CurbsideCollection) then everywhere the union of DeliveryMethods is used would have to be updated.

Is there a way to change DeliveryMethod so that it can only be extended upon and specified as a type so that it's children can be used but it can never be used on it's own?

CodePudding user response:

Is there a way to change DeliveryMethod so that it can only be extended upon and specified as a type so that it's children can be used but it can never be used on it's own?

Unless I misunderstand your question, this is quite literally how interfaces work. You can't use an interface on it's own.

class Order {
  …
  public delivery: DeliveryMethod; // Defined as `DeliveryMethod` but can only ever point to a derived type instance
}

In other words:

val order.delivery = DeliveryMethod() // Does not compile

CodePudding user response:

This is a great case for a type alias.

In your situation, I'd rename DeliveryMethod to something like DeliveryMethodBase, then create a type alias DeliveryMethod which is a union of all of the interfaces which extend from DeliveryMethodBase, and use that type wherever you need.

If/when you need to extend the union, you'll only need to do it in one place: the alias definition.

interface DeliveryMethodBase {
  specialInstructions: string;
}

interface InStorePickup extends DeliveryMethodBase {
  // ...
}

interface Shipment extends DeliveryMethodBase {
  // ...
}

type DeliveryMethod = InStorePickup | Shipment;

class Order {
  // …
  public delivery: DeliveryMethod;
}
  •  Tags:  
  • Related