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?

g.pickardou
fonte

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 .

Thomas
fonte
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});
Brocco
fonte
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
Hasan A Yousef
fonte
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.

Gabriel Castillo Prada
fonte
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:');
Monkpit
fonte
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

David Sherret
fonte
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);
 }
malbarmavi
fonte
-1

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

Isso funcionou para mim.

error('This is the ',null,1000)
numpsi
fonte
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.

Rick
fonte
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