¿Cómo pasar parámetros opcionales mientras se omiten algunos otros parámetros opcionales?

282

Dada la siguiente firma:

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

¿Cómo puedo llamar a la función error() no especificando el titleparámetro, sino configurando autoHideAfterpara decir 1000?

g.pickardou
fuente

Respuestas:

307

Como se especifica en la documentación , 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);

Enlace del patio de recreo .

Thomas
fuente
66
@ BBi7 Creo que entendió mal la documentación. El ?se agrega en la definición de la función , pero la pregunta es acerca de llamar realmente a la función.
Thomas
Hola @Thomas. Entiendo totalmente la documentación y sé que debes agregar el. después del parámetro en la definición de la función. Pero, relacionado con la llamada a una función con parámetros opcionales, supongo que pasará indefinido si no corresponde. Por lo general, trato de encontrar formas de hacer parámetros opcionales como parámetros finales para que no pueda pasar frente a indefinido. Pero obviamente, si tiene muchos, entonces necesitaría pasar indefinido o algo no verdadero. No estoy seguro de a qué me refería cuando publiqué originalmente. Lo que significa que no sé si fue editado, pero lo que veo ahora está bien, correcto.
BBi7
2
@ BBi7 No hubo ediciones recientes. Bien, no importa entonces :) (Tenga en cuenta que en realidad debe pasar undefinedpara obtener el mismo comportamiento que omitir por completo el argumento. Simplemente "cualquier cosa que no sea verdadera" no funcionará, porque TypeScript en realidad se compara con void 0cuál es una forma más segura de escribir undefined. )
Thomas
71

Lamentablemente, no hay nada como esto en TypeScript (más detalles aquí: https://github.com/Microsoft/TypeScript/issues/467 )

Pero para evitar esto, puede cambiar sus parámetros para que sean una interfaz:

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
fuente
¿Podría decirme si puedo llamar al método de error como esto, error ({mensaje: 'prueba'}), creo que no podemos, así que error ({mensaje: 'prueba', autoHideAFter: indefinido}), pero lo que espero es un error (mensaje), si no pasé otros parámetros, debería tomar los valores de los parámetros predeterminados.
Cegone
37

puede usar una variable opcional por ?o si tiene varias variables opcionales por ..., por ejemplo:

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

En lo anterior:

  • name es requerido
  • country es obligatorio y tiene un valor predeterminado
  • address es opcional
  • hobbies es una serie de parámetros opcionales
Hasan A Yousef
fuente
2
¿No deberían los pasatiempos ser escritos como una matriz?
ProgramadorPor
44
Hay una información útil en esta respuesta, pero no responde la pregunta. La pregunta es, según lo veo, cómo se pueden omitir / omitir varios parámetros opcionales y establecer solo parámetros específicos.
MaxB
2
país no es obligatorio, es un parámetro opcional que tiene un valor predeterminado de 'CA' en lugar de indefinido. Si es necesario, ¿cuál es el punto de proporcionar el valor predeterminado?
Anand Bhushan
19

Otro enfoque es:

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

Entonces, cuando desee omitir el parámetro de título, simplemente envíe los datos así:

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

Prefiero estas opciones porque me permite agregar más parámetros sin tener que enviar los demás.

Gabriel Castillo Prada
fuente
¿Cómo pasarías también un valor predeterminado title?
Dan Dascalescu
13

Esto es casi lo mismo que la respuesta de @Brocco, pero con un ligero giro: solo pasa parámetros opcionales en un objeto. (Y también hacer que los parámetros sean opcionales).

Termina siendo como los ** kwargs de Python, pero no exactamente.

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
fuente
5

Puede especificar múltiples firmas de métodos en la interfaz y luego tener múltiples sobrecargas de métodos en el método de clase:

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

Ahora todo esto 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);

... y el errormétodo de INotificationServicetendrá las siguientes opciones:

Inteligencia de sobrecarga

Patio de recreo

David Sherret
fuente
9
Solo una nota que recomendaría contra esto y en su lugar pasar un objeto y poner estos parámetros como propiedades en ese objeto ... es mucho menos trabajo y el código será más legible.
David Sherret
2

Puede crear un método auxiliar que acepte una base de parámetros de un objeto en argumentos de error

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

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

Puede intentar establecer el título en nulo.

Esto funcionó para mí.

error('This is the ',null,1000)
numpsi
fuente
3
Esto funcionaría ya que si el parámetro de función tiene un valor predeterminado cuando envió nulo a ese parámetro de función no se establecerá en su valor predeterminado
Okan SARICA
-2

Puede hacer esto sin una interfaz.

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

use el ?operador como parámetro opcional.

Almiar
fuente
pero esto no le permite especificar messageyautoHideAfter
Simon_Weaver
3
no contesta la pregunta o no la leyó. Quiere saber cómo llamar a un método con múltiples parámetros opcionales, sin tener que especificar el primer opcional si solo desea ingresar el segundo.
Gregfr