【问题标题】:TypeScript: How to make an optional second argument required based on the value of the first argumentTypeScript:如何根据第一个参数的值制作可选的第二个参数
【发布时间】:2019-08-05 23:48:51
【问题描述】:

假设我有一个需要 2 个参数的函数,根据第一个参数的值,可能需要也可能不需要第二个参数。

例如:

function calculate(item: 'icon' | 'category', state: IState): void {

    if (arg1 === 'icon') {
        // code in which I don't need to access anything in state
    } 

    if (arg1 === 'category') {
        // code in which I do need to access state
    }

}

如果我按原样运行,我会得到一个错误,如果我写

calculate('icon') // will cause an error

这也会引发错误,因为我没有为第二个参数传递有效值

calculate('icon', null) // will also cause an error

为了不出错,我必须这样称呼它

calculate('icon', this.state) // acceptable as long as 'this.state' meets the IState definition

如果第一个参数 = 'icon',我希望能够在不传递第二个参数的情况下调用该函数。像这样

calculate('icon') // should not cause an error

但是,如果我这样调用计算应该会导致错误

calculate('category') // should cause an error

任何帮助将不胜感激!

【问题讨论】:

    标签: typescript typescript-typings


    【解决方案1】:

    你可以使用多个重载:

    function calculate(item: 'icon'): void
    function calculate(item: 'category', state: IState): void
    function calculate(item: 'icon' | 'category', state?: IState): void {
    
        if (item === 'icon') {
            // code in which I don't need to access anything in state
        } 
    
        if (item === 'category' && state) {
            // code in which I do need to access state
        }
    
    }
    calculate("icon")
    calculate("category") //error
    

    【讨论】:

      【解决方案2】:

      这是我最终采用的解决方案。如果有人知道更好的方法,请分享!

      type ConditionalOptions<T, K extends keyof T> = T[K] extends null ? [] : [T[K]];
      interface IPossibleValues {
          icon: {
              state: IState;
          };
          theme: null;
          category: {
              state: IState;
              cardItem: any;
          };
      }
      
      calculate = <T extends keyof IPossibleValues>(
          type: T,
          ...options: ConditionalOptions<IPossibleValues, T>
      ): string => {
          // code here
      }
      

      如果使用这种方法,接口IPossibleValues中每个键的值就是需要作为第二个arg传入calculate的值。例子:

      calculate('icon') // this will cause an error since no 'state' is passed in
      calculate('icon', { state: stateVal }) // this will not generate a type error
      
      calculate('theme') // this will not cause any type errors
      calculate('theme', someValue) // this will cause an error
      
      calculate('category', {
          state: stateVal,
          cardItem: cardVal,
      }) // this will not cause an error
      calculate('category', { state: stateVal }) // this will cause an error because 'cardItem' was not passed in
      
      

      【讨论】:

      • 我比 Titian 的回答更喜欢这个解决方案,因为它更干燥。唯一的缺点是,当您实际调用函数时,TS 不会立即为您提供第二个参数所需的格式,它只会说“缺少选项”。
      猜你喜欢
      • 2021-12-20
      • 2018-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-24
      • 1970-01-01
      • 2020-10-21
      • 1970-01-01
      相关资源
      最近更新 更多