【问题标题】:How to pass optional parameters while omitting some other optional parameters?如何在省略其他一些可选参数的同时传递可选参数?
【发布时间】:2015-08-24 10:00:04
【问题描述】:

给出以下签名:

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

我怎样才能调用函数error() 指定title参数,但设置autoHideAfter1000

【问题讨论】:

    标签: typescript


    【解决方案1】:

    documentation 中指定,使用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);
    

    Playground link.

    【讨论】:

    • @BBi7 我认为您误解了文档。 ? 被添加到函数definition 中,但问题是关于实际调用 函数。
    • 嗨@Thomas 我完全理解文档并且知道你必须添加?在函数定义中的参数之后。但是,与调用带有可选参数的函数有关,如果不适用,我假设传递 undefined 。我通常会尝试找到将可选参数作为结束参数的方法,这样我就不能通过与未定义的比较。但很明显,如果你有很多,那么你需要传递 undefined 或任何不真实的东西。我不确定我最初发布时指的是什么。意思是我不知道它是否被编辑,但我现在看到的很好。
    • @BBi7 最近没有编辑。好吧,那没关系 :) (请注意,您实际上必须通过 undefined 才能获得与完全省略参数相同的行为。只是“任何不真实的东西”都行不通,因为 TypeScript actuallyvoid 0 相比这是一种更安全的写作方式undefined。)
    【解决方案2】:

    不幸的是,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({message : 'test'}),我想,我们不能,所以 error({message : 'test' , autoHideAFter: undefined}),但我期待的是错误(消息),如果我没有传递其他参数,它应该从默认参数中获取值。
    【解决方案3】:

    另一种方法是:

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

    所以当你想省略标题参数时,只需像这样发送数据:

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

    我更喜欢这个选项,因为允许我添加更多参数而无需发送其他参数。

    【讨论】:

    • 如何将默认值传递给title
    • @DanDascalescu ..., options?: {title?: string} = {title: "my default"}, ...
    【解决方案4】:

    您可以通过? 使用可选变量,或者如果您有多个可选变量通过...,例如:

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

    在上面:

    • name 为必填项
    • country 是必需的并且有一个默认值
    • address 是可选的
    • hobbies 是一个可选参数数组

    【讨论】:

    • 不应该把爱好写成数组吗?
    • 这个答案中有一个有用的信息,但它没有回答这个问题。在我看来,问题是如何绕过/跳过几个可选参数并只设置特定参数。
    • country 不是必需的,它是一个可选参数,默认值为 'CA' 而不是 undefined。如果需要,那么提供默认值有什么意义?
    【解决方案5】:

    这与@Brocco 的答案几乎相同,但略有不同:仅在对象中传递可选参数。(并且还使 params 对象可选)。

    它最终有点像 Python 的 **kwargs,但不完全一样。

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

    【讨论】:

      【解决方案6】:

      您可以在接口上指定多个方法签名,然后在类方法上具有多个方法重载:

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

      ...和INotificationServiceerror 方法将有以下选项:

      Playground

      【讨论】:

      • 请注意,我建议不要这样做,而是传入一个对象并将这些参数作为属性放在该对象上...这样工作量要少得多,代码也会更易读。跨度>
      • 这不是一个好主意。如果我有三个字符串参数但只想省略其中一个参数怎么办?这不起作用,因为所有三个覆盖都具有相同的签名
      • params 分配看起来非常脆弱且难以维护。此外,如果将来需要另一个参数,那就需要更多的杂耍。
      【解决方案7】:

      您可以创建一个辅助方法,根据错误参数接受一个对象参数

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

      【讨论】:

        【解决方案8】:

        在 TS 中,您还可以将参数设置为 Object,并使对象的值可选,这样您就不必定义每个参数,只需定义您想要使用的参数。

        public functionBeingCalled(obj: {status?: number, error?: string, message?: string}) {
          if(obj.message) { console.log(obj.message) }
        }
        
        this.functionBeingCalled({message: 'Error Detected'})

        【讨论】:

          【解决方案9】:

          在这种情况下,您可以为那些不想覆盖的可选参数使用“未定义”值

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

          你可以像这样调用错误方法

          error("it works", undefined, 20);
          

          小心null 在这里不起作用。

          【讨论】:

            【解决方案10】:

            您可以在没有界面的情况下执行此操作。

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

            使用? 运算符作为可选参数。

            【讨论】:

            • 但这不允许您以任何方式指定messageautoHideAfter
            • 你没有回答这个问题或者你没有阅读它。他想知道如何调用具有多个可选参数的方法,而如果他只想输入第二个可选参数,则不必指定第一个可选参数。
            【解决方案11】:

            您可以尝试将 title 设置为 null。

            这对我有用。

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

            【讨论】:

            • 这不会起作用,因为如果函数参数具有默认值,当您将 null 发送到该函数参数时,该函数参数将不会设置为其默认值
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-03-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-12-04
            相关资源
            最近更新 更多