Как передать необязательные параметры, опуская некоторые другие необязательные параметры?


282

Учитывая следующую подпись:

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

Как я могу вызвать функцию, error() не указав titleпараметр, а установив, autoHideAfterчтобы сказать 1000?

Ответы:


308

Как указано в документации , используйте 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 Я думаю, вы неправильно поняли документацию. ?Добавляется в функции определения , но речь идет о фактически вызова функции.
Томас

Привет @ Томас Я полностью понимаю документацию и знаю, что вы должны добавить? после параметра в определении функции. Но в связи с вызовом функции с необязательным параметром (ами) я бы предположил, что передача не определена, если это не применимо. Обычно я пытаюсь найти способы сделать необязательный параметр (и) в качестве конечного (ых) параметра (ов), чтобы я мог просто не передавать против undefined. Но, очевидно, если у вас их много, вам нужно будет передать неопределенное или что-то неправдивое. Я не уверен, что я имел в виду, когда я первоначально отправил. Это означает, что я не знаю, было ли это отредактировано, но то, что я вижу сейчас, правильно.
BBi7

2
@ BBi7 Не было недавних изменений. Ладно, не бери в голову :) (Обратите внимание, что вы на самом деле должны пройти, undefinedчтобы получить то же поведение, что и пропустить аргумент целиком. Просто «все неправдивое» не сработает, потому что TypeScript фактически сравнивает с тем, void 0что является более безопасным способом записи) undefined. )
Томас

71

К сожалению, в TypeScript нет ничего подобного (подробнее здесь: https://github.com/Microsoft/TypeScript/issues/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});

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

37

Вы можете использовать необязательную переменную с помощью ?или, если у вас есть несколько необязательных переменных ..., например:

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

В приведенном выше:

  • name необходимо
  • country является обязательным и имеет значение по умолчанию
  • address необязательно
  • hobbies массив необязательных параметров

2
Разве хобби не должно быть напечатано как массив?
ProgrammerPer

4
В этом ответе есть полезная информация, но она не отвечает на вопрос. Вопрос в том, как я вижу, как можно обойти / пропустить несколько необязательных параметров и установить только конкретные.
MaxB

2
страна не обязательна, это необязательный параметр, имеющий значение по умолчанию «CA» вместо неопределенного. если это требуется, то какой смысл предоставлять значение по умолчанию?
Ананд Бхушан

19

Другой подход:

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

Поэтому, если вы хотите опустить параметр title, просто отправьте данные следующим образом:

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

Я бы предпочел эту опцию, потому что позволяет мне добавить больше параметров, не отправляя другие.


Как бы вы также передали значение по умолчанию title?
Дан Даскалеску

13

Это почти то же самое, что и ответ @Brocco, но с небольшим поворотом: только передавать необязательные параметры в объекте. (А также сделать объект params необязательным).

Это в конечном итоге напоминает ** 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будет иметь следующие параметры:

Перегрузка intellisense

Игровая площадка


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

Вы можете попытаться установить заголовок на ноль.

Это сработало для меня.

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.