Як передавати необов'язкові параметри, опускаючи деякі інші необов’язкові параметри?


282

Дано такий підпис:

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

Як я можу викликати функцію error() не вказуючи titleпараметр, а налаштування autoHideAfterсказати 1000?

Відповіді:


307

Як зазначено в документації , використовуйте 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);

Дитячий майданчик посилання .


6
@ BBi7 Я думаю, ви неправильно зрозуміли документацію. Значення ?додано у визначенні функції , але питання стосується фактичного виклику функції.
— Томас

Привіт @Thomas Я повністю розумію документацію і знаю, що потрібно додати? після параметра у визначенні функції. Але, стосовно виклику функції з необов'язковим параметром, я вважаю, що це не визначено, якщо це не застосовується. Я, як правило, намагаюся знайти способи зробити необов'язкові параметри, як кінцеві параметри, щоб я просто не міг переходити проти невизначеного. Але очевидно, якщо у вас їх багато, то вам знадобиться пройти невизначене або що-небудь неправдоподібне. Я не впевнений, на що я мав на увазі, коли я спочатку розмістив повідомлення. Це означає, що я не знаю, чи це було відредаговано, але те, що я зараз вважаю правильно.
— BBi7

2
@ BBi7 Не було останніх змін. Гаразд, майте на увазі тоді :) (Зауважте, що ви насправді маєте пройти, undefinedщоб отримати таку саму поведінку, як повністю випускати аргумент. Просто "все, що не є правдою", не буде працювати, тому що TypeScript насправді порівнює з тим, void 0що це більш безпечний спосіб написання undefined. )
— Томас

71

На жаль, у TypeScript нічого подібного немає (детальніше тут: https://github.com/Microsoft/TypeScript/isissue/467 )

Але, щоб обійти це, ви можете змінити парами, щоб бути інтерфейсом:

export interface IErrorParams {
  message: string;
  title?: string;
  autoHideAfter?: number;
}

export interface INotificationService {
  error(params: IErrorParams);
}

//then to call it:
error({message: 'msg', autoHideAfter: 42});

Скажіть, будь ласка, чи можу я назвати метод помилки таким, помилка ({message: 'test'}), я думаю, ми не можемо, тому помилка ({message: 'test', autoHideAFter: undefined}), але що я очікую на помилку (повідомлення), якщо я не передав інші парамери, він повинен приймати значення з параметрів за замовчуванням.
— Cegone

37

ви можете використовувати необов'язкові змінні за ?або, якщо у вас є кілька необов'язкових змінних ..., наприклад:

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

У вищесказаному:

  • name необхідно
  • country є обов'язковим і має значення за замовчуванням
  • address необов’язково
  • hobbies - це масив необов'язкових парам

2
Чи не варто хобі вводити як масив?
— ПрограмістPer

4
У цій відповіді є корисна інформація, але вона не відповідає на запитання. Питання полягає в тому, як я бачу, як можна обійти / пропустити кілька необов’язкових параметрів і встановити лише конкретні.
— MaxB

2
країна не потрібна, це необов'язковий парам із значенням за замовчуванням "CA" замість невизначеного. якщо це потрібно, то який сенс надавати значення за замовчуванням?
— Ананд Бхушан

19

Ще один підхід:

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

Отже, коли ви хочете опустити параметр заголовка, просто надішліть такі дані:

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

Я вважаю за краще цей параметр, оскільки дозволяє мені додавати більше параметрів без необхідності надсилати інші.


Як би ви також передали значення за замовчуванням title?
— Дан Даскалеску

13

Це майже те саме, що відповідь @Brocco, але з невеликим поворотом: передайте лише об'єктивні параметри в об'єкт. (А також зробіть об'єкт парами необов’язковим).

Це в кінцевому підсумку схоже на ** kwargs Python, але не зовсім так.

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

Ви можете вказати декілька підписів методу в інтерфейсі, а потім мати кілька перевантажень методу на метод класу:

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

Тепер все це спрацює:

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

... і errorметод INotificationServiceбуде мати наступні варіанти:

Інтелісенс перевантаження

Ігровий майданчик


9
Лише зауважте, що я рекомендував би проти цього, а замість цього передати об’єкт і поставити ці параметри як властивості на цьому об’єкті ... це набагато менше роботи, і код буде більш читабельним.
— Девід Шеррет

2

Ви можете створити допоміжний метод, який приймає базу параметрів одного об’єкта на аргументах помилок

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

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

-1

Ви можете спробувати встановити заголовок на null.

Це працювало для мене.

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

3
Це не працює, оскільки якщо параметр функції має значення за замовчуванням, коли ви надіслали нулю для цього функціонального параметра, він не встановить його за замовчуванням
— Okan SARICA,

-2

Це можна зробити без інтерфейсу.

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

використовувати ?оператор як необов'язковий параметр.


але це не дозволяє вам жодним чином вказати messageіautoHideAfter
— Simon_Weaver

3
ви не відповідаєте на запитання або не прочитали його. Він хоче знати, як викликати метод з декількома необов'язковими параметрами, не вказуючи перший необов'язковий, якщо він хоче лише ввести другий.
— Грегфр
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.