interfacce fluenti, indipendenti dall'ordine;

3

Ho un semplice esempio di utilizzo di un'interfaccia fluente per allegare eventi in JavaScript

function attach(fn){
  let handler,to;
  handler = fn;
  attach.to = function (el) {
    to = document.getElementById(el);
    return attach;
  }
  attach.on = function (type) {
    to.addEventListener(type,fn);
    return attach;
  }
  return attach;
}

attach(()=>console.log("hello world")).to("div").on("click");

attualmente dipende dall'ordine in cui vengono chiamate le funzioni. Questo esempio è abbastanza semplice con solo altri due attributi che devono essere impostati, ma cosa accadrebbe se ce ne fossero molti altri? Esiste un modello preferito per lasciare che le funzioni vengano chiamate in qualsiasi ordine e quindi eseguire il risultato quando è stato impostato n di proprietà?

    
posta wootscootinboogie 20.08.2016 - 20:05
fonte

2 risposte

2

Finché stai restituendo la stessa cosa puoi continuare a chiamare le stesse cose (è, si spera, fluente). Se desideri controllare l'ordine di ciò che è consentito chiamare, devi restituire qualcosa che consente solo di chiamare ciò che vuoi consentire.

Questi sono chiamati iDSL : lingue specifiche del dominio interno. Invece di restituire sempre la stessa cosa con lo stesso insieme di funzioni, si restituisce un oggetto diverso con funzioni diverse. Quando questa lingua è costruita all'interno di un'altra lingua (come javascript) chiamiamo il DSL interno.

Il mondo Javascript non è strongmente digitato . Non ti verrà detto che non puoi chiamare una funzione finché non esegui il codice. Ma, a parte la mancanza di suggerimenti quando le persone si sparano al piede, questo funziona. In pratica, impedirai alle persone di chiamare roba fuori servizio.

Non li ho usati molto in Javascript, ma questa domanda java che ho chiesto molto tempo fa rimanda a dei buoni modelli di esempio che danno il tipo di controllo di cui pensi tu stia parlando. A parte il tuo IDE che non è così utile, tutto funzionerebbe allo stesso modo in Javascript.

Javascript potrebbe permetterti di implementarlo in un modo diverso. Posso immaginare di abilitare e disabilitare direttamente le funzioni che vuoi disponibili, in modo dinamico. Non sono sicuro di quanto sarebbe brutto.

Se hai visto jQuery in azione hai visto fluente Javascript. Non saresti il primo a estenderlo a iDSL. Ecco un esempio .

    
risposta data 20.08.2016 - 21:44
fonte
2

Il modo in cui questo viene solitamente raggiunto è utilizzando i valori di ritorno dei metodi fluenti per codificare lo stato corrente e le transizioni valide della macchina di stato del builder. In altre parole: si restituisce un oggetto che ha solo i metodi per le proprietà che non sono ancora stati impostati.

Sfortunatamente, questo può facilmente portare a un'esplosione combinatoria di oggetti, come puoi vedere qui nel mio "piccolo" esempio per un generatore di email con quattro proprietà: mittente, destinatario, oggetto e messaggio.

"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}'); }
}

Ecco 16 classi per codificare la seguente macchina a stati:

Questo ti consente di inviare un'email usando una qualsiasi delle seguenti combinazioni:

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();

Se ti dimentichi di impostare una qualsiasi delle proprietà, riceverai un errore:

 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();

E se provi a specificare una proprietà due volte, riceverai anche un errore:

 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");

Sfortunatamente, sembra che almeno l'inferenza di tipo di WebStorm non sia abbastanza intelligente da darti il completamento automatico corretto, a meno che tu non lo aiuti insieme ad alcune annotazioni sui tipi:

"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}'); }
}

Se lo definisci in questo modo, ottieni controllo del tipo e utile completamento automatico, ad es. digitando

mail().

visualizzerà from , to , re e msg , ma non send , mentre digitando

mail().re("Something").from("Something").

mostrerà solo to e msg e

mail().from("").to("").re("").msg("").

visualizzerà solo send .

    
risposta data 23.08.2016 - 04:23
fonte

Leggi altre domande sui tag