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?

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 .


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

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

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.


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:');

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


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

-1

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

Cela a fonctionné pour moi.

error('This is the ',null,1000)

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.


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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.