Como passar parâmetros opcionais ao omitir outros parâmetros opcionais?


282

Dada a seguinte assinatura:

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

Como posso chamar a função error() não especificando o titleparâmetro, mas configurando autoHideAfterpara dizer 1000?

Respostas:


307

Conforme especificado na documentação , use 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);

Link para parque infantil .


6
@ BBi7 Acho que você não entendeu a documentação. O ?é adicionado na definição da função , mas a questão é realmente chamar a função.
Thomas

Oi @ Thomas Eu entendo totalmente a documentação e sei que você deve adicionar o? após o parâmetro na definição da função. Mas, relacionado à chamada de uma função com parâmetro (s) opcional (ais), eu assumiria a passagem indefinida, se não aplicável. Geralmente, tento encontrar maneiras de criar parâmetros opcionais como parâmetros finais, para que eu não possa passar vs. indefinido. Mas, obviamente, se você tiver muitos, precisará passar indefinido ou algo que não seja verdade. Não sei ao que estava me referindo quando postei originalmente. Ou seja, não sei se foi editado, mas o que vejo agora está correto.
BBi7 # 15/18

2
@ BBi7 Não houve edições recentes. Ok, não se preocupe, então :) (Observe que você realmente deve passar undefinedpara obter o mesmo comportamento que deixar de fora o argumento completamente. Apenas "qualquer coisa que não seja verdade " não funcionará, porque o TypeScript realmente se compara ao void 0que é uma maneira mais segura de escrever undefined. )
Thomas

71

Infelizmente, não há nada parecido com isso no TypeScript (mais detalhes aqui: https://github.com/Microsoft/TypeScript/issues/467 )

Mas, para contornar isso, você pode alterar seus parâmetros para ser uma 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});

Você poderia dizer, posso chamar o método de erro como este, error ({message: 'test'}), acho que não podemos, então erro ({message: 'test', autoHideAFter: undefined}), mas o que eu estou esperando é erro (mensagem), se eu não passar outros parâmetros, ele deve pegar os valores dos parâmetros padrão.
Cegone

37

você pode usar variável opcional por ?ou se você tiver várias variáveis ​​opcionais por ..., exemplo:

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

No exemplo acima:

  • name É necessário
  • country é obrigatório e tem um valor padrão
  • address é opcional
  • hobbies é uma matriz de parâmetros opcionais

2
Os hobbies não devem ser digitados como uma matriz?
ProgrammerPer

4
Há uma informação útil nesta resposta, mas ela não responde à pergunta. A questão é, a meu ver, como alguém pode ignorar / pular vários parâmetros opcionais e definir apenas parâmetros específicos.
MaxB 28/03/19

2
país não é obrigatório, é um parâmetro opcional com um valor padrão de 'CA' em vez de indefinido. se for necessário, qual é o sentido de fornecer valor padrão?
Anand Bhushan

19

Outra abordagem é:

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

Então, quando você quiser omitir o parâmetro title, basta enviar os dados assim:

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

Eu prefiro essas opções porque me permite adicionar mais parâmetros sem precisar enviar os outros.


Como você também passaria um valor padrão title?
Dan Dascalescu 04/03

13

Isso é quase o mesmo que a resposta de @Brocco, mas com uma ligeira torção: apenas passe parâmetros opcionais em um objeto. (E também torne opcional o objeto params).

Ele acaba sendo como os ** kwargs de Python, mas não exatamente.

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

Você pode especificar várias assinaturas de método na interface e ter várias sobrecargas de método no método 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
    }
}

Agora tudo isso funcionará:

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

... e o errormétodo de INotificationServiceterá as seguintes opções:

Sobrecarga intellisense

Parque infantil


9
Apenas uma observação que eu recomendaria contra isso e, em vez disso, passava um objeto e colocava esses parâmetros como propriedades nesse objeto ... é muito menos trabalhoso e o código ficará mais legível.
David Sherret 01/03

2

Você pode criar um método auxiliar que aceite uma base de parâmetro de um objeto nos argumentos de erro

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

 getError(args: { message: string, title?: string, autoHideAfter?: number }) {
    return error(args.message, args.title, args.autoHideAfter);
 }

-1

Você pode tentar definir o título como nulo.

Isso funcionou para mim.

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

3
Este trabalho woulndt pois se o parâmetro de função tem um valor padrão quando você enviou null a esse parâmetro função não definido para seu valor padrão
Okan Sarica

-2

Você pode fazer isso sem uma interface.

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

use o ?operador como um parâmetro opcional.


mas isso não permite que você especifique messageeautoHideAfter
Simon_Weaver 19/11/16

3
você não responde à pergunta ou não a leu. Ele quer saber como chamar um método com vários parâmetros opcionais, sem precisar especificar o primeiro opcional, se ele quiser apenas inserir o segundo.
Gregfr
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.