【问题标题】:How to infer parameter type of a overloaded callback?如何推断重载回调的参数类型?
【发布时间】:2022-12-18 11:53:05
【问题描述】:

我正在尝试在打字稿中定义一个类型安全的 nodejs 风格的回调。我想将 err 定义为 Error(如果存在)或将 data 定义为 T(如果不存在)。

  1. 如果我使用这段代码
    export interface SafeCallback<T> {
        (err: unknown): void;
        (err: undefined, data: T): void;
    }
    
    const subscribe = <T>(callback: SafeCallback<T>) => {
        let result: T;
        try {
            // result = something
        } catch (e) {
            callback(e);
            return;
        }
    
        callback(undefined, result);
    };
    
    subscribe<{id: string}>((err, data?) => {
        if (!err) {
            console.log(data.id);
        }
    });
    
    

    我得到'data' is of type 'unknown'.

    1. 如果我从data 中删除问号,我得到 Argument of type '(err: undefined, data: { id: string; }) =&gt; void' is not assignable to parameter of type 'SafeCallback&lt;{ id: string; }&gt;'

    我尝试了在第一次重载中定义 err: Error 的两种情况,但它没有改变任何东西。

    还有什么我应该尝试的吗?

    谢谢!

【问题讨论】:

  • This approach 是我能得到的最接近的并且是类型安全的。我尝试过的任何其他方法都遇到了限制或错误。它能满足您的需求吗?如果是这样,我可以写一个答案来解释;如果没有,我错过了什么?
  • 嘿!请随意发布作为答案,谢谢!

标签: typescript callback type-safety


【解决方案1】:

有条件的类型可能是?

export type SafeCallback<T> = {
    <errorType>(err: errorType, data: errorType extends undefined ? T : null): void;
};


const subscribe = <T>(callback: SafeCallback<T>) => {
    let result: T;
    try {
      // result logic
    } catch (e) {
        callback(e, null);
        return;
    }

    callback(undefined, result);
};

subscribe<{ id: string }>((err, data) => {
    if (data !== null) {
        console.log("data  = " + data.id);
    } else {
        console.log("err = " + err);
    }
});

编辑 : 刚看到@jclaz 回复。从他的回应中摘取一些东西:

export interface SafeCallback3<T> {
    <errorType>(...args:( errorType extends undefined ? [err: undefined, data: T] : [err: errorType] )): void;
}

这可以防止在 catch 中抛出错误。

const subscribe3 = <T>(callback: SafeCallback3<T>) => {
    let result: T;
        try {
        // ...
        } catch (e) {
            callback(e);
            return;
    }

    callback(undefined, result);
};

subscribe<{ id: string }>((...args) => {
  const [err, data] = args;
  if (!err) {
    console.log(data.id);
  } else {
    err.message
  }
});

【讨论】:

    猜你喜欢
    • 2021-04-09
    • 1970-01-01
    • 2020-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-15
    • 1970-01-01
    • 2021-06-04
    相关资源
    最近更新 更多