Comment passer des paramètres facultatifs tout en omettant certains autres paramètres facultatifs?

282

Étant donné la signature suivante:

export interface INotificationService {
    error(message: string, title?: string, autoHideAfter?: number);
}

Comment puis-je appeler la fonction error() ne spécifiant pas le titleparamètre, mais le réglage autoHideAfterà dire 1000?

g.pickardou
la source

Réponses:

307

Comme spécifié dans la documentation , utilisez undefined:

export interface INotificationService {
    error(message: string, title?: string, autoHideAfter? : number);
}

class X {
    error(message: string, title?: string, autoHideAfter?: number) {
        console.log(message, title, autoHideAfter);
    }
}

new X().error("hi there", undefined, 1000);

Lien aire de jeux .

Thomas
la source
6
@ BBi7 Je pense que vous avez mal compris la documentation. Le ?est ajouté dans la définition de la fonction , mais la question concerne l' appel réel de la fonction.
Thomas
Salut @Thomas Je comprends parfaitement la documentation et sais que vous devez ajouter le? après le paramètre dans la définition de la fonction. Mais, en ce qui concerne l'appel d'une fonction avec des paramètres facultatifs, je suppose que le passage est indéfini s'il n'est pas applicable. En général, j'essaie de trouver des moyens de créer des paramètres facultatifs en tant que paramètres finaux afin que je ne puisse tout simplement pas passer par rapport à undefined. Mais évidemment, si vous en avez plusieurs, vous devrez passer non défini ou quoi que ce soit de non véridique. Je ne sais pas à quoi je faisais référence lorsque j'ai posté à l'origine. Ce qui signifie que je ne sais pas s'il a été modifié, mais ce que je vois maintenant est correct.
BBi7
2
@ BBi7 Il n'y a eu aucune modification récente. D'accord, alors faites attention :) (Notez que vous devez en fait réussir undefinedpour obtenir le même comportement que de supprimer complètement l'argument. Juste "tout ce qui n'est pas véridique" ne fonctionnera pas, car TypeScript se compare en fait à void 0ce qui est une manière plus sûre d'écrire undefined. )
Thomas
71

Malheureusement, il n'y a rien de tel dans TypeScript (plus de détails ici: https://github.com/Microsoft/TypeScript/issues/467 )

Mais pour contourner cela, vous pouvez changer vos paramètres pour être une interface:

export interface IErrorParams {
  message: string;
  title?: string;
  autoHideAfter?: number;
}

export interface INotificationService {
  error(params: IErrorParams);
}

//then to call it:
error({message: 'msg', autoHideAfter: 42});
Brocco
la source
Pourriez-vous s'il vous plaît dire, puis-je appeler la méthode d'erreur comme ceci, erreur ({message: 'test'}), je pense que nous ne pouvons pas, donc erreur ({message: 'test', autoHideAFter: undefined}), mais ce que j'attends, c'est une erreur (message), si je n'ai pas passé d'autres paramètres, il faut prendre les valeurs des paramètres par défaut.
Cegone
37

vous pouvez utiliser la variable facultative par ?ou si vous avez plusieurs variables facultatives par ..., par exemple:

function details(name: string, country="CA", address?: string, ...hobbies: string) {
    // ...
}

Au dessus:

  • name est requis
  • country est requis et a une valeur par défaut
  • address est facultatif
  • hobbies est un tableau de paramètres facultatifs
Hasan A Yousef
la source
2
Les passe-temps ne doivent-ils pas être saisis sous forme de tableau?
ProgrammerPer
4
Il y a une information utile dans cette réponse, mais elle ne répond pas à la question. La question est, à mon avis, comment on peut contourner / ignorer plusieurs paramètres facultatifs et n'en définir que des spécifiques.
MaxB
2
country n'est pas requis, c'est un paramètre facultatif ayant une valeur par défaut de 'CA' au lieu d'undefined. si c'est nécessaire, quel est l'intérêt de fournir une valeur par défaut?
Anand Bhushan
19

Une autre approche est:

error(message: string, options?: {title?: string, autoHideAfter?: number});

Donc, quand vous voulez omettre le paramètre title, envoyez simplement les données comme ça:

error('the message', { autoHideAfter: 1 })

Je préfère cette option car elle me permet d'ajouter plus de paramètres sans avoir à envoyer les autres.

Gabriel Castillo Prada
la source
Comment transmettriez-vous également une valeur par défaut à title?
Dan Dascalescu
13

C'est presque la même chose que la réponse de @Brocco, mais avec une légère torsion: ne passez que des paramètres optionnels dans un objet. (Et aussi rendre l'objet params facultatif).

Cela finit par être un peu comme les kwargs de Python, mais pas exactement.

export interface IErrorParams {
  title?: string;
  autoHideAfter?: number;
}

export interface INotificationService {
  // make params optional so you don't have to pass in an empty object
  // in the case that you don't want any extra params
  error(message: string, params?: IErrorParams);
}

// all of these will work as expected
error('A message with some params but not others:', {autoHideAfter: 42});
error('Another message with some params but not others:', {title: 'StackOverflow'});
error('A message with all params:', {title: 'StackOverflow', autoHideAfter: 42});
error('A message with all params, in a different order:', {autoHideAfter: 42, title: 'StackOverflow'});
error('A message with no params at all:');
Monkpit
la source
5

Vous pouvez spécifier plusieurs signatures de méthode sur l'interface, puis avoir plusieurs surcharges de méthode sur la méthode de classe:

interface INotificationService {
    error(message: string, title?: string, autoHideAfter?: number);
    error(message: string, autoHideAfter: number);
}

class MyNotificationService implements INotificationService {
    error(message: string, title?: string, autoHideAfter?: number);
    error(message: string, autoHideAfter?: number);
    error(message: string, param1?: (string|number), param2?: number) {
        var autoHideAfter: number,
            title: string;

        // example of mapping the parameters
        if (param2 != null) {
            autoHideAfter = param2;
            title = <string> param1;
        }
        else if (param1 != null) {
            if (typeof param1 === "string") {
                title = param1;
            }
            else {
                autoHideAfter = param1;
            }
        }

        // use message, autoHideAfter, and title here
    }
}

Maintenant, tout cela fonctionnera:

var service: INotificationService = new MyNotificationService();
service.error("My message");
service.error("My message", 1000);
service.error("My message", "My title");
service.error("My message", "My title", 1000);

... et la errorméthode de INotificationServiceaura les options suivantes:

Surcharge Intellisense

Terrain de jeux

David Sherret
la source
9
Juste une note que je recommanderais contre cela et plutôt passer un objet et mettre ces paramètres en tant que propriétés sur cet objet ... c'est beaucoup moins de travail et le code sera plus lisible.
David Sherret
2

Vous pouvez créer une méthode d'assistance qui accepte une base de paramètres d'un objet sur des arguments d'erreur

 error(message: string, title?: string, autoHideAfter?: number){}

 getError(args: { message: string, title?: string, autoHideAfter?: number }) {
    return error(args.message, args.title, args.autoHideAfter);
 }
malbarmavi
la source
-1

Vous pouvez essayer de définir le titre sur null.

Cela a fonctionné pour moi.

error('This is the ',null,1000)
numpsi
la source
3
Cela ne fonctionnera pas car si le paramètre de fonction a une valeur par défaut lorsque vous avez envoyé null à ce paramètre de fonction ne sera pas défini sur sa valeur par défaut
Okan SARICA
-2

Vous pouvez le faire sans interface.

class myClass{
  public error(message: string, title?: string, autoHideAfter? : number){
    //....
  }
}

utilisez l' ?opérateur comme paramètre facultatif.

Meule
la source
mais cela ne vous permet pas de spécifier messageetautoHideAfter
Simon_Weaver
3
vous ne répondez pas à la question ou vous ne l'avez pas lue. Il veut savoir comment appeler une méthode avec plusieurs paramètres optionnels, sans avoir à spécifier la première option s'il ne veut entrer que le second.
Gregfr