请教个 ts 函数重载的问题?

enum Method {
  Add = '+',
  Reduce = '-'
}

interface AddParams {
  method: Method.Add,
  nums: [string, string]
}

interface ReduceParams {
  method: Method.Reduce,
  nums: [number, number]
}

function calc(params: AddParams): string
function calc(params: ReduceParams): number
function calc(params: AddParams | ReduceParams): string | number {
  switch (params.method) {
    case Method.Add:
      return params.nums[0] + params.nums[1];
    case Method.Reduce:
      return params.nums[0] - params.nums[1];
  }
}

const calc2 = (params: AddParams | ReduceParams): string | number => {
  return calc(params);
};

calc2({ method: Method.Add, nums: ['1', '2'] });
calc2({ method: Method.Reduce, nums: [1, 2] });

会提示以下错误,该怎么让它不报错呢
image.png

阅读 2k
3 个回答

提示是没有匹配的重载吧。
calc2赋值的函数接收一个参数类型为AddParams|ReduceParams,传递给calc确实定义的重载中没有匹配上的。
或者直接把calc的重载定义为function calc(params: AddParams | ReduceParams): string | number;这样?

推荐使用泛型,而不是重载

type calcParams<T> = T extends string ? AddParams :  ReduceParams 

function calc<
    T extends string | number,
    D extends calcParams<T> = calcParams<T>
>(params: D): D['nums'][number] {
  switch (params.method) {
    case Method.Add:
      params
      return params.nums[0] + params.nums[1];
    case Method.Reduce:
      return params.nums[0] - params.nums[1];
  }
}

calc({ method: Method.Add, nums: ['1', '2'] });
calc({ method: Method.Reduce, nums: [1, 2] });

在构造外层包装的时候,也要符合内部调用的类型约束T extends string | number


const calc2 = <T extends string | number>(params: calcParams<T>): any 
    => calc<T,typeof params>(params);

calc2({ method: Method.Add, nums: ['1', '2'] });
calc2({ method: Method.Reduce, nums: [1, 2] });

没有匹配的参数,可以自己定义一个匹配参数

function calc(params: AddParams): string
function calc(params: ReduceParams): number
function calc(params: AddParams | ReduceParams): string | number
function calc(params: AddParams | ReduceParams): string | number {
    switch (params.method) {
        case Method.Add:
            return params.nums[0] + params.nums[1];
        case Method.Reduce:
            return params.nums[0] - params.nums[1];
    }
}

现在函数的调用是三种情况,AddParams、ReduceParams、(AddParams | ReduceParams)

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题