Jak przekazać parametry opcjonalne, pomijając niektóre inne parametry opcjonalne?

282

Biorąc pod uwagę następujący podpis:

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

Jak mogę wywołać funkcję error() nie określającą titleparametru, ale ustawienie autoHideAfterdo powiedzenia 1000?

g.pickardou
źródło

Odpowiedzi:

307

Zgodnie z dokumentacją użyj 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 do placu zabaw .

Tomasz
źródło
6
@ BBi7 Myślę, że źle zrozumiałeś dokumentację. ?Dodaje się w funkcji definicji , ale pytanie jest o faktycznie wywołanie funkcji.
Thomas
Cześć @ Thomas Całkowicie rozumiem dokumentację i wiem, że musisz ją dodać? po parametrze w definicji funkcji. Ale w związku z wywoływaniem funkcji z opcjonalnymi parametrami zakładam, że przekazanie jest niezdefiniowane, jeśli nie dotyczy. Generalnie staram się znaleźć sposoby, aby opcjonalny parametr (y) jako parametr końcowy (parametry końcowe), więc po prostu nie mogłem przejść w porównaniu z niezdefiniowanym. Ale oczywiście, jeśli masz ich wiele, musisz przejść niezdefiniowany lub coś nierzeczywistego. Nie jestem pewien, o czym mówiłem, kiedy pisałem. Czyli nie wiem, czy był edytowany, ale to, co widzę teraz, jest w porządku.
BBi7
2
@ BBi7 Brak ostatnich zmian. Okej, nieważne więc :) (Pamiętaj, że musisz przejść, undefinedaby uzyskać takie samo zachowanie, jak całkowite pominięcie argumentu. Po prostu „wszystko, co nie jest prawdą” nie zadziała, ponieważ TypeScript faktycznie porównuje, z void 0którym jest bezpieczniejszym sposobem pisania undefined. )
Thomas
71

Niestety nie ma czegoś takiego w TypeScript (więcej szczegółów tutaj: https://github.com/Microsoft/TypeScript/issues/467 )

Aby obejść ten problem, możesz zmienić swoje parametry na interfejs:

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
źródło
Czy możesz powiedzieć, czy mogę wywołać metodę błędu w ten sposób, błąd ({message: 'test'}), myślę, że nie możemy, więc błąd ({message: 'test', autoHideAFter: undefined}), ale to czego oczekuję to błąd (komunikat), jeśli nie przeszedłem innych parametrów, to pogrubiłbym wartości z parametrów domyślnych.
Cegone
37

możesz użyć zmiennej opcjonalnej przez ?lub jeśli masz wiele zmiennych opcjonalnych przez ..., na przykład:

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

W powyższym:

  • name jest wymagane
  • country jest wymagany i ma wartość domyślną
  • address jest opcjonalne
  • hobbies to tablica opcjonalnych parametrów
Hasan A Yousef
źródło
2
Czy hobby nie powinno być wpisywane jako tablica?
ProgrammerPer
4
Ta odpowiedź zawiera przydatne informacje, ale nie odpowiada na pytanie. Pytanie brzmi, jak widzę, w jaki sposób można ominąć / pominąć kilka opcjonalnych parametrów i ustawić tylko określone.
MaxB
2
kraj nie jest wymagany, jest to opcjonalny parametr o domyślnej wartości „CA” zamiast niezdefiniowanej. jeśli jest to wymagane, jaki jest sens podania wartości domyślnej?
Anand Bhushan
19

Innym podejściem jest:

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

Więc jeśli chcesz pominąć parametr title, po prostu wyślij dane w ten sposób:

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

Wolę te opcje, ponieważ pozwala mi dodać więcej parametrów bez konieczności wysyłania innych.

Gabriel Castillo Prada
źródło
W jaki sposób przekażesz również wartość domyślną title?
Dan Dascalescu
13

Jest to prawie to samo co odpowiedź @Brocco, ale z lekkim zwrotem: przekazuj tylko opcjonalne parametry w obiekcie. (A także uczyń obiekt params opcjonalnym).

Ostatecznie przypomina trochę kwargów ** Pythona, ale nie do końca.

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
źródło
5

Możesz określić wiele podpisów metod w interfejsie, a następnie mieć przeciążenia wielu metod w metodzie klasy:

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

Teraz wszystkie będą działać:

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

... a errormetoda INotificationServicebędzie miała następujące opcje:

Przeciążenie intellisense

Plac zabaw

David Sherret
źródło
9
Uwaga: odradzałbym to i zamiast tego przekazał obiekt i umieścił te parametry jako właściwości na tym obiekcie ... to o wiele mniej pracy, a kod będzie bardziej czytelny.
David Sherret
2

Możesz utworzyć metodę pomocniczą, która akceptuje parametry jednego obiektu na podstawie argumentów błędów

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

 getError(args: { message: string, title?: string, autoHideAfter?: number }) {
    return error(args.message, args.title, args.autoHideAfter);
 }
malbarmavi
źródło
-1

Możesz spróbować ustawić tytuł na null.

To zadziałało dla mnie.

error('This is the ',null,1000)
numpsi
źródło
3
To woulndt działa, ponieważ jeśli parametr funkcji ma wartość domyślną po wysłaniu wartości NULL do tego parametru funkcji, nie zostanie ustawiona na wartość domyślną
Okan SARICA
-2

Możesz to zrobić bez interfejsu.

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

użyj ?operatora jako parametru opcjonalnego.

Stóg
źródło
ale nie pozwala to na żadne określenie messageiautoHideAfter
Simon_Weaver
3
nie odpowiadasz na pytanie lub go nie czytałeś. Chce wiedzieć, jak wywołać metodę z wieloma opcjonalnymi parametrami, bez konieczności określania pierwszej opcjonalnej, jeśli chce tylko wprowadzić drugą.
Gregfr,