关于函数的回调函数重载问题如何解决

当我们有一个函数,他的回调函数参数个数不固定时,该如何编写 ts 类型才能正确推导。
示例如下:

// 一个简单的函数
type TCB = {
    (a: number, b: string): number;
    (a: string): string;
}
function fn(str: string, cb: TCB): number {
  if (new Date().getTime() % 2 === 0) {
    cb(1, str); // cb: (number, string) => number;
  } else {
    callback(str); // cb: (string) => string;
  }
  return 2222;
}

我们该如何写类型,才能让用户在使用时 cb 得到正确的参数类型推导呢?

期望使用时,cb 回调函数可以正确重载。

// 只有一个参数,对应 TCB 的第二种情况
fn('sss', a => {
  console.log(a);
  return '2222';
});

// 两个参数,对应 TCB 的第一种情况
fn('sss', (a, b) => {
  console.log(a, b);
  return 2222;
});
阅读 1.6k
1 个回答

if 条件只有在运行时才知道,而运行时没有类型,所以你想要的,不能靠 TypeScript 来处理。
另外,TCB 是一个重载函数类型,这就表示 cb: TCB 必须是一个重载函数,不然类型就匹配不上。
所以这里并不是声明可以使用 TCB 两个重载中的一个,而是必须要实现了两个重载的函数。

按你的想法,应该是这样:

// 一个简单的函数
type F1 = (a: number, b: string) => number;
type F2 = (a: string) => string;

function isF1(f: F1 | F2): f is F1 {
    return f.length == 2;
}

function fn(str: string, cb: F1 | F2): number {
    if (isF1(cb)) {
        cb(1, str);
    } else {
        cb(str);
    }

    return 2222;
}

// 只有一个参数,对应 TCB 的第二种情况
fn("sss", (a: string) => {
    console.log(a);
    return "2222";
});

// 两个参数,对应 TCB 的第一种情况
fn("sss", (a, b) => {
    console.log(a, b);
    return 2222;
});
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进