The way this is usually achieved is by using the return values of the fluent methods to encode the current state and the valid transitions of the builder's state machine. In other words: you return an object which only has the methods for the properties that haven't been set yet.
Unfortunately, this can easily lead to a combinatorial explosion of objects, as you can see here in my "little" example for an email builder with four properties: sender, recipient, subject, and message.
"use strict";
function mail() { return new VoidEmailBuilder(); }
class EmailBuilder {
constructor(old, param) {
for (const prop in old) this[prop] = old[prop];
for (const prop in param) this[prop] = param[prop];
}
toString() { return `Email from "${this.sender}" to "${this.recipient}" regarding "${this.subject}" saying "${this.message}".`; }
}
class VoidEmailBuilder extends EmailBuilder {
from(sender) { return new EmailBuilderWithSender( this, {sender: sender} ); }
to (recipient) { return new EmailBuilderWithRecipient(this, {recipient: recipient}); }
re (subject) { return new EmailBuilderWithSubject( this, {subject: subject} ); }
msg (message) { return new EmailBuilderWithMessage( this, {message: message} ); }
}
class EmailBuilderWithSender extends EmailBuilder {
to (recipient) { return new EmailBuilderWithSenderAndRecipient(this, {recipient: recipient}); }
re (subject) { return new EmailBuilderWithSenderAndSubject( this, {subject: subject} ); }
msg (message) { return new EmailBuilderWithSenderAndMessage( this, {message: message} ); }
}
class EmailBuilderWithRecipient extends EmailBuilder {
from(sender) { return new EmailBuilderWithSenderAndRecipient( this, {sender: sender} ); }
re (subject) { return new EmailBuilderWithRecipientAndSubject(this, {subject: subject}); }
msg (message) { return new EmailBuilderWithRecipientAndMessage(this, {message: message}); }
}
class EmailBuilderWithSubject extends EmailBuilder {
from(sender) { return new EmailBuilderWithSenderAndSubject( this, {sender: sender} ); }
to (recipient) { return new EmailBuilderWithRecipientAndSubject(this, {recipient: recipient}); }
msg (message) { return new EmailBuilderWithSubjectAndMessage( this, {message: message} ); }
}
class EmailBuilderWithMessage extends EmailBuilder {
from(sender) { return new EmailBuilderWithSenderAndMessage( this, {sender: sender} ); }
to (recipient) { return new EmailBuilderWithRecipientAndMessage(this, {recipient: recipient}); }
re (subject) { return new EmailBuilderWithSubjectAndMessage( this, {subject: subject} ); }
}
class EmailBuilderWithSenderAndRecipient extends EmailBuilder {
re (subject) { return new EmailBuilderWithSenderAndRecipientAndSubject(this, {subject: subject}); }
msg (message) { return new EmailBuilderWithSenderAndRecipientAndMessage(this, {message: message}); }
}
class EmailBuilderWithSenderAndSubject extends EmailBuilder {
to (recipient) { return new EmailBuilderWithSenderAndRecipientAndSubject(this, {recipient: recipient}); }
msg (message) { return new EmailBuilderWithSenderAndSubjectAndMessage( this, {message: message} ); }
}
class EmailBuilderWithSenderAndMessage extends EmailBuilder {
to (recipient) { return new EmailBuilderWithSenderAndRecipientAndMessage(this, {recipient: recipient}); }
re (subject) { return new EmailBuilderWithSenderAndSubjectAndMessage( this, {subject: subject} ); }
}
class EmailBuilderWithRecipientAndSubject extends EmailBuilder {
from(sender) { return new EmailBuilderWithSenderAndRecipientAndSubject( this, {sender: sender} ); }
msg (message) { return new EmailBuilderWithRecipientAndSubjectAndMessage(this, {message: message}); }
}
class EmailBuilderWithRecipientAndMessage extends EmailBuilder {
from(sender) { return new EmailBuilderWithSenderAndRecipientAndMessage( this, {sender: sender} ); }
re (subject) { return new EmailBuilderWithRecipientAndSubjectAndMessage(this, {subject: subject}); }
}
class EmailBuilderWithSubjectAndMessage extends EmailBuilder {
from(sender) { return new EmailBuilderWithSenderAndSubjectAndMessage( this, {sender: sender }); }
to (recipient) { return new EmailBuilderWithRecipientAndSubjectAndMessage(this, {recipient: recipient}); }
}
class EmailBuilderWithSenderAndRecipientAndSubject extends EmailBuilder {
msg (message) { return new Email(this, {message: message}); }
}
class EmailBuilderWithSenderAndRecipientAndMessage extends EmailBuilder {
re (subject) { return new Email(this, {subject: subject}); }
}
class EmailBuilderWithSenderAndSubjectAndMessage extends EmailBuilder {
to (recipient) { return new Email(this, {recipient: recipient}); }
}
class EmailBuilderWithRecipientAndSubjectAndMessage extends EmailBuilder {
from(sender) { return new Email(this, {sender: sender}); }
}
class Email extends EmailBuilder {
send() { console.log(`Sending this email: ${this}`); }
}
That's 16 classes to encode the following state machine:
This allows you to send an email using any of the following combinations:
mail().from("Me").to("You").re("ES Builder").msg("Bla!").send();
mail().from("Me").to("You").msg("Bla!").re("ES Builder").send();
mail().from("Me").re("ES Builder").to("You").msg("Bla!").send();
mail().from("Me").re("ES Builder").msg("Bla!").to("You").send();
mail().from("Me").msg("Bla!").to("You").re("ES Builder").send();
mail().from("Me").msg("Bla!").re("ES Builder").to("You").send();
mail().to("You").from("Me").re("ES Builder").msg("Bla!").send();
mail().to("You").from("Me").msg("Bla!").re("ES Builder").send();
mail().to("You").re("ES Builder").from("Me").msg("Bla!").send();
mail().to("You").re("ES Builder").msg("Bla!").from("Me").send();
mail().to("You").msg("Bla!").from("Me").re("ES Builder").send();
mail().to("You").msg("Bla!").re("ES Builder").from("Me").send();
mail().re("ES Builder").from("Me").to("You").msg("Bla!").send();
mail().re("ES Builder").from("Me").msg("Bla!").to("You").send();
mail().re("ES Builder").to("You").from("Me").msg("Bla!").send();
mail().re("ES Builder").to("You").msg("Bla!").from("Me").send();
mail().re("ES Builder").msg("Bla!").from("Me").to("You").send();
mail().re("ES Builder").msg("Bla!").to("You").from("Me").send();
mail().msg("Bla!").from("Me").to("You").re("ES Builder").send();
mail().msg("Bla!").from("Me").re("ES Builder").to("You").send();
mail().msg("Bla!").to("You").from("Me").re("ES Builder").send();
mail().msg("Bla!").to("You").re("ES Builder").from("Me").send();
mail().msg("Bla!").re("ES Builder").from("Me").to("You").send();
mail().msg("Bla!").re("ES Builder").to("You").from("Me").send();
If you forget to set any one of the properties, you will get an error:
mail().from("Me").to("You").re("ES Builder").send();
mail().from("Me").to("You").msg("Bla!").send();
mail().from("Me").re("ES Builder").to("You").send();
mail().from("Me").re("ES Builder").msg("Bla!").send();
mail().from("Me").msg("Bla!").to("You").send();
mail().from("Me").msg("Bla!").re("ES Builder").send();
mail().to("You").from("Me").re("ES Builder").send();
mail().to("You").from("Me").msg("Bla!").send();
mail().to("You").re("ES Builder").from("Me").send();
mail().to("You").re("ES Builder").msg("Bla!").send();
mail().to("You").msg("Bla!").from("Me").send();
mail().to("You").msg("Bla!").re("ES Builder").send();
mail().re("ES Builder").from("Me").to("You").send();
mail().re("ES Builder").from("Me").msg("Bla!").send();
mail().re("ES Builder").to("You").from("Me").send();
mail().re("ES Builder").to("You").msg("Bla!").send();
mail().re("ES Builder").msg("Bla!").from("Me").send();
mail().re("ES Builder").msg("Bla!").to("You").send();
mail().msg("Bla!").from("Me").to("You").send();
mail().msg("Bla!").from("Me").re("ES Builder").send();
mail().msg("Bla!").to("You").from("Me").send();
mail().msg("Bla!").to("You").re("ES Builder").send();
mail().msg("Bla!").re("ES Builder").from("Me").send();
mail().msg("Bla!").re("ES Builder").to("You").send();
And if you try to specify a property twice, you will also get an error:
mail().from("Me").to("You").re("ES Builder").msg("Bla!").from("Again");
mail().from("Me").to("You").re("ES Builder").msg("Bla!").to("Again");
mail().from("Me").to("You").re("ES Builder").msg("Bla!").re("Again");
mail().from("Me").to("You").re("ES Builder").msg("Bla!").msg("Again");
mail().from("Me").to("You").msg("Bla!").re("ES Builder").from("Again");
mail().from("Me").to("You").msg("Bla!").re("ES Builder").to("Again");
mail().from("Me").to("You").msg("Bla!").re("ES Builder").re("Again");
mail().from("Me").to("You").msg("Bla!").re("ES Builder").msg("Again");
mail().from("Me").re("ES Builder").to("You").msg("Bla!").from("Again");
mail().from("Me").re("ES Builder").to("You").msg("Bla!").to("Again");
mail().from("Me").re("ES Builder").to("You").msg("Bla!").re("Again");
mail().from("Me").re("ES Builder").to("You").msg("Bla!").msg("Again");
mail().from("Me").re("ES Builder").msg("Bla!").to("You").from("Again");
mail().from("Me").re("ES Builder").msg("Bla!").to("You").to("Again");
mail().from("Me").re("ES Builder").msg("Bla!").to("You").re("Again");
mail().from("Me").re("ES Builder").msg("Bla!").to("You").msg("Again");
mail().from("Me").msg("Bla!").to("You").re("ES Builder").from("Again");
mail().from("Me").msg("Bla!").to("You").re("ES Builder").to("Again");
mail().from("Me").msg("Bla!").to("You").re("ES Builder").re("Again");
mail().from("Me").msg("Bla!").to("You").re("ES Builder").msg("Again");
mail().from("Me").msg("Bla!").re("ES Builder").to("You").from("Again");
mail().from("Me").msg("Bla!").re("ES Builder").to("You").to("Again");
mail().from("Me").msg("Bla!").re("ES Builder").to("You").re("Again");
mail().from("Me").msg("Bla!").re("ES Builder").to("You").msg("Again");
mail().to("You").from("Me").re("ES Builder").msg("Bla!").from("Again");
mail().to("You").from("Me").re("ES Builder").msg("Bla!").to("Again");
mail().to("You").from("Me").re("ES Builder").msg("Bla!").re("Again");
mail().to("You").from("Me").re("ES Builder").msg("Bla!").msg("Again");
mail().to("You").from("Me").msg("Bla!").re("ES Builder").from("Again");
mail().to("You").from("Me").msg("Bla!").re("ES Builder").to("Again");
mail().to("You").from("Me").msg("Bla!").re("ES Builder").re("Again");
mail().to("You").from("Me").msg("Bla!").re("ES Builder").msg("Again");
mail().to("You").re("ES Builder").from("Me").msg("Bla!").from("Again");
mail().to("You").re("ES Builder").from("Me").msg("Bla!").to("Again");
mail().to("You").re("ES Builder").from("Me").msg("Bla!").re("Again");
mail().to("You").re("ES Builder").from("Me").msg("Bla!").msg("Again");
mail().to("You").re("ES Builder").msg("Bla!").from("Me").from("Again");
mail().to("You").re("ES Builder").msg("Bla!").from("Me").to("Again");
mail().to("You").re("ES Builder").msg("Bla!").from("Me").re("Again");
mail().to("You").re("ES Builder").msg("Bla!").from("Me").msg("Again");
mail().to("You").msg("Bla!").from("Me").re("ES Builder").from("Again");
mail().to("You").msg("Bla!").from("Me").re("ES Builder").to("Again");
mail().to("You").msg("Bla!").from("Me").re("ES Builder").re("Again");
mail().to("You").msg("Bla!").from("Me").re("ES Builder").msg("Again");
mail().to("You").msg("Bla!").re("ES Builder").from("Me").from("Again");
mail().to("You").msg("Bla!").re("ES Builder").from("Me").to("Again");
mail().to("You").msg("Bla!").re("ES Builder").from("Me").re("Again");
mail().to("You").msg("Bla!").re("ES Builder").from("Me").msg("Again");
mail().re("ES Builder").from("Me").to("You").msg("Bla!").from("Again");
mail().re("ES Builder").from("Me").to("You").msg("Bla!").to("Again");
mail().re("ES Builder").from("Me").to("You").msg("Bla!").re("Again");
mail().re("ES Builder").from("Me").to("You").msg("Bla!").msg("Again");
mail().re("ES Builder").from("Me").msg("Bla!").to("You").from("Again");
mail().re("ES Builder").from("Me").msg("Bla!").to("You").to("Again");
mail().re("ES Builder").from("Me").msg("Bla!").to("You").re("Again");
mail().re("ES Builder").from("Me").msg("Bla!").to("You").msg("Again");
mail().re("ES Builder").to("You").from("Me").msg("Bla!").from("Again");
mail().re("ES Builder").to("You").from("Me").msg("Bla!").to("Again");
mail().re("ES Builder").to("You").from("Me").msg("Bla!").re("Again");
mail().re("ES Builder").to("You").from("Me").msg("Bla!").msg("Again");
mail().re("ES Builder").to("You").msg("Bla!").from("Me").from("Again");
mail().re("ES Builder").to("You").msg("Bla!").from("Me").to("Again");
mail().re("ES Builder").to("You").msg("Bla!").from("Me").re("Again");
mail().re("ES Builder").to("You").msg("Bla!").from("Me").msg("Again");
mail().re("ES Builder").msg("Bla!").from("Me").to("You").from("Again");
mail().re("ES Builder").msg("Bla!").from("Me").to("You").to("Again");
mail().re("ES Builder").msg("Bla!").from("Me").to("You").re("Again");
mail().re("ES Builder").msg("Bla!").from("Me").to("You").msg("Again");
mail().re("ES Builder").msg("Bla!").to("You").from("Me").from("Again");
mail().re("ES Builder").msg("Bla!").to("You").from("Me").to("Again");
mail().re("ES Builder").msg("Bla!").to("You").from("Me").re("Again");
mail().re("ES Builder").msg("Bla!").to("You").from("Me").msg("Again");
mail().msg("Bla!").from("Me").to("You").re("ES Builder").from("Again");
mail().msg("Bla!").from("Me").to("You").re("ES Builder").to("Again");
mail().msg("Bla!").from("Me").to("You").re("ES Builder").re("Again");
mail().msg("Bla!").from("Me").to("You").re("ES Builder").msg("Again");
mail().msg("Bla!").from("Me").re("ES Builder").to("You").from("Again");
mail().msg("Bla!").from("Me").re("ES Builder").to("You").to("Again");
mail().msg("Bla!").from("Me").re("ES Builder").to("You").re("Again");
mail().msg("Bla!").from("Me").re("ES Builder").to("You").msg("Again");
mail().msg("Bla!").to("You").from("Me").re("ES Builder").from("Again");
mail().msg("Bla!").to("You").from("Me").re("ES Builder").to("Again");
mail().msg("Bla!").to("You").from("Me").re("ES Builder").re("Again");
mail().msg("Bla!").to("You").from("Me").re("ES Builder").msg("Again");
mail().msg("Bla!").to("You").re("ES Builder").from("Me").from("Again");
mail().msg("Bla!").to("You").re("ES Builder").from("Me").to("Again");
mail().msg("Bla!").to("You").re("ES Builder").from("Me").re("Again");
mail().msg("Bla!").to("You").re("ES Builder").from("Me").msg("Again");
mail().msg("Bla!").re("ES Builder").from("Me").to("You").from("Again");
mail().msg("Bla!").re("ES Builder").from("Me").to("You").to("Again");
mail().msg("Bla!").re("ES Builder").from("Me").to("You").re("Again");
mail().msg("Bla!").re("ES Builder").from("Me").to("You").msg("Again");
mail().msg("Bla!").re("ES Builder").to("You").from("Me").from("Again");
mail().msg("Bla!").re("ES Builder").to("You").from("Me").to("Again");
mail().msg("Bla!").re("ES Builder").to("You").from("Me").re("Again");
mail().msg("Bla!").re("ES Builder").to("You").from("Me").msg("Again");
Unfortunately, it seems like at least WebStorm's type inference is not quite smart enough to give you correct autocompletion, unless you help it along with some type annotations:
"use strict";
/**
* @returns {!VoidEmailBuilder}
*/
function mail() { return new VoidEmailBuilder(); }
class EmailBuilder {
/**
* @param {!EmailBuilder} old
* @param {!{sender: string, recipient: string, subject: string, message: string}} param
*/
constructor(old, param) {
for (const prop in old) this[prop] = old[prop];
for (const prop in param) this[prop] = param[prop];
}
/**
* @override
* @final
* @returns {!string}
*/
toString() { return `Email from "${this.sender}" to "${this.recipient}" regarding "${this.subject}" saying "${this.message}".`; }
}
/** @final
* @extends EmailBuilder */
class VoidEmailBuilder extends EmailBuilder {
/**
* @param {!string} sender
* @returns {!EmailBuilderWithSender}
*/
from(sender) { return new EmailBuilderWithSender( this, {sender: sender} ); }
/**
* @param {!string} recipient
* @returns {!EmailBuilderWithRecipient}
*/
to (recipient) { return new EmailBuilderWithRecipient(this, {recipient: recipient}); }
/**
* @param {!string} subject
* @returns {!EmailBuilderWithSubject}
*/
re (subject) { return new EmailBuilderWithSubject( this, {subject: subject} ); }
/**
* @param {!string} message
* @returns {!EmailBuilderWithMessage}
*/
msg (message) { return new EmailBuilderWithMessage( this, {message: message} ); }
}
/** @final
* @extends EmailBuilder */
class EmailBuilderWithSender extends EmailBuilder {
/**
* @param {!string} recipient
* @returns {!EmailBuilderWithSenderAndRecipient}
*/
to (recipient) { return new EmailBuilderWithSenderAndRecipient(this, {recipient: recipient}); }
/**
* @param {!string} subject
* @returns {!EmailBuilderWithSenderAndSubject}
*/
re (subject) { return new EmailBuilderWithSenderAndSubject( this, {subject: subject} ); }
/**
* @param {!string} message
* @returns {!EmailBuilderWithSenderAndMessage}
*/
msg (message) { return new EmailBuilderWithSenderAndMessage( this, {message: message} ); }
}
/** @final
* @extends EmailBuilder */
class EmailBuilderWithRecipient extends EmailBuilder {
/**
* @param {!string} sender
* @returns {!EmailBuilderWithSenderAndRecipient}
*/
from(sender) { return new EmailBuilderWithSenderAndRecipient( this, {sender: sender} ); }
/**
* @param {!string} subject
* @returns {!EmailBuilderWithRecipientAndSubject}
*/
re (subject) { return new EmailBuilderWithRecipientAndSubject(this, {subject: subject}); }
/**
* @param {!string} message
* @returns {!EmailBuilderWithRecipientAndMessage}
*/
msg (message) { return new EmailBuilderWithRecipientAndMessage(this, {message: message}); }
}
/** @final
* @extends EmailBuilder */
class EmailBuilderWithSubject extends EmailBuilder {
/**
* @param {!string} sender
* @returns {!EmailBuilderWithSenderAndSubject}
*/
from(sender) { return new EmailBuilderWithSenderAndSubject( this, {sender: sender} ); }
/**
* @param {!string} recipient
* @returns {!EmailBuilderWithRecipientAndSubject}
*/
to (recipient) { return new EmailBuilderWithRecipientAndSubject(this, {recipient: recipient}); }
/**
* @param {!string} message
* @returns {!EmailBuilderWithSubjectAndMessage}
*/
msg (message) { return new EmailBuilderWithSubjectAndMessage( this, {message: message} ); }
}
/** @final
* @extends EmailBuilder */
class EmailBuilderWithMessage extends EmailBuilder {
/**
* @param {!string} sender
* @returns {!EmailBuilderWithSenderAndMessage}
*/
from(sender) { return new EmailBuilderWithSenderAndMessage( this, {sender: sender} ); }
/**
* @param {!string} recipient
* @returns {!EmailBuilderWithRecipientAndMessage}
*/
to (recipient) { return new EmailBuilderWithRecipientAndMessage(this, {recipient: recipient}); }
/**
* @param {!string} subject
* @returns {!EmailBuilderWithSubjectAndMessage}
*/
re (subject) { return new EmailBuilderWithSubjectAndMessage( this, {subject: subject} ); }
}
/** @final
* @extends EmailBuilder */
class EmailBuilderWithSenderAndRecipient extends EmailBuilder {
/**
* @param {!string} subject
* @returns {!EmailBuilderWithSenderAndRecipientAndSubject}
*/
re (subject) { return new EmailBuilderWithSenderAndRecipientAndSubject(this, {subject: subject}); }
/**
* @param {!string} message
* @returns {!EmailBuilderWithSenderAndRecipientAndMessage}
*/
msg (message) { return new EmailBuilderWithSenderAndRecipientAndMessage(this, {message: message}); }
}
/** @final
* @extends EmailBuilder */
class EmailBuilderWithSenderAndSubject extends EmailBuilder {
/**
* @param {!string} recipient
* @returns {!EmailBuilderWithSenderAndRecipientAndSubject}
*/
to (recipient) { return new EmailBuilderWithSenderAndRecipientAndSubject(this, {recipient: recipient}); }
/**
* @param {!string} message
* @returns {!EmailBuilderWithSenderAndSubjectAndMessage}
*/
msg (message) { return new EmailBuilderWithSenderAndSubjectAndMessage( this, {message: message} ); }
}
/** @final
* @extends EmailBuilder */
class EmailBuilderWithSenderAndMessage extends EmailBuilder {
/**
* @param {!string} recipient
* @returns {!EmailBuilderWithSenderAndRecipientAndMessage}
*/
to (recipient) { return new EmailBuilderWithSenderAndRecipientAndMessage(this, {recipient: recipient}); }
/**
* @param {!string} subject
* @returns {!EmailBuilderWithSenderAndSubjectAndMessage}
*/
re (subject) { return new EmailBuilderWithSenderAndSubjectAndMessage( this, {subject: subject} ); }
}
/** @final
* @extends EmailBuilder */
class EmailBuilderWithRecipientAndSubject extends EmailBuilder {
/**
* @param {!string} sender
* @returns {!EmailBuilderWithSenderAndRecipientAndSubject}
*/
from(sender) { return new EmailBuilderWithSenderAndRecipientAndSubject( this, {sender: sender} ); }
/**
* @param {!string} message
* @returns {!EmailBuilderWithRecipientAndSubjectAndMessage}
*/
msg (message) { return new EmailBuilderWithRecipientAndSubjectAndMessage(this, {message: message}); }
}
/** @final
* @extends EmailBuilder */
class EmailBuilderWithRecipientAndMessage extends EmailBuilder {
/**
* @param {!string} sender
* @returns {!EmailBuilderWithSenderAndRecipientAndMessage}
*/
from(sender) { return new EmailBuilderWithSenderAndRecipientAndMessage( this, {sender: sender} ); }
/**
* @param {!string} subject
* @returns {!EmailBuilderWithRecipientAndSubjectAndMessage}
*/
re (subject) { return new EmailBuilderWithRecipientAndSubjectAndMessage(this, {subject: subject}); }
}
/** @final
* @extends EmailBuilder */
class EmailBuilderWithSubjectAndMessage extends EmailBuilder {
/**
* @param {!string} sender
* @returns {!EmailBuilderWithSenderAndSubjectAndMessage}
*/
from(sender) { return new EmailBuilderWithSenderAndSubjectAndMessage( this, {sender: sender }); }
/**
* @param {!string} recipient
* @returns {!EmailBuilderWithRecipientAndSubjectAndMessage}
*/
to (recipient) { return new EmailBuilderWithRecipientAndSubjectAndMessage(this, {recipient: recipient}); }
}
/** @final
* @extends EmailBuilder */
class EmailBuilderWithSenderAndRecipientAndSubject extends EmailBuilder {
/**
* @param {!string} message
* @returns {!Email}
*/
msg (message) { return new Email(this, {message: message}); }
}
/** @final
* @extends EmailBuilder */
class EmailBuilderWithSenderAndRecipientAndMessage extends EmailBuilder {
/**
* @param {!string} subject
* @returns {!Email}
*/
re (subject) { return new Email(this, {subject: subject}); }
}
/** @final
* @extends EmailBuilder */
class EmailBuilderWithSenderAndSubjectAndMessage extends EmailBuilder {
/**
* @param {!string} recipient
* @returns {!Email}
*/
to (recipient) { return new Email(this, {recipient: recipient}); }
}
/** @final
* @extends EmailBuilder */
class EmailBuilderWithRecipientAndSubjectAndMessage extends EmailBuilder {
/**
* @param {!string} sender
* @returns {!Email}
*/
from(sender) { return new Email(this, {sender: sender}); }
}
/** @final
* @extends EmailBuilder */
class Email extends EmailBuilder {
send() { console.log(`Sending this email: ${this}`); }
}
If you define it like that, you get type checking and useful autocompletion, e.g. typing
mail().
will display from
, to
, re
, and msg
, but not send
, whereas typing
mail().re("Something").from("Something").
will only display to
and msg
, and
mail().from("").to("").re("").msg("").
will only display send
.