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;
}
