【问题标题】:Is it possible to create a type-safe function that receives a callback and the callback's params with TypeScript?是否可以使用 TypeScript 创建一个接收回调和回调参数的类型安全函数?
【发布时间】:2022-01-25 19:14:06
【问题描述】:

我正在尝试创建一个接收两个参数的函数:一个回调函数和该函数的参数(props)。例如:

const callbackFunction = (a: number) => a + 2;
const callbackFunctionProps = 5;
callbackWrapper(callbackFunction, callbackFunctionProps);

我希望 TypeScript 检查以“callbackFunctionProps”给出的道具是否是“callbackFunction”的有效道具。有没有办法在不使用泛型的情况下做到这一点? function 和 props 的类型无关紧要,只要它们相互匹配即可。

【问题讨论】:

  • 不使用泛型...?
  • “不管是什么类型......”要求与“......没有泛型”并不匹配。有什么理由不使用我们应该注意的泛型?
  • @raina77 和 Majed Badawi 的回答对我来说都很好。谢谢您的帮助。我认为我缺少的是您始终可以在不指定类型的情况下调用泛型类型函数,并且打字稿会尝试推断它。

标签: javascript typescript


【解决方案1】:

泛型正是“类型无关紧要”情况的补救措施。这是 with 泛型的一种可能方法:

const callbackWrapper = <I extends Array<unknown>, O>(fn: (...fnArgs: I) => O, ...args: I): O => 
{
    const result = fn(...args);
    console.log(`CALLED WITH ${args.join(', ')}, RESULT IS ${result}`);
    return result;
}

const callbackFunctionA = (a: number) => a + 2; 
const callbackFunctionPropsA = 5;

const callbackFunctionB = (a: number, b: number) => a + b + 2;
const callbackFunctionPropsB1 = 10;
const callbackFunctionPropsB2 = 30;

callbackWrapper(callbackFunctionA, callbackFunctionPropsA); 
// "CALLED WITH 5, RESULT IS 7" 
callbackWrapper(callbackFunctionB, callbackFunctionPropsB1, callbackFunctionPropsB2);
// "CALLED WITH 10, 30, RESULT IS 42"

诀窍是在两个地方使用I(创建的泛型的类型参数):作为传递函数的参数类型(...fnArgs: I 部分)和作为传递给回调的参数类型(...args: I 部分)。如果它们不匹配,编译器就会对你大喊:

callbackWrapper(callbackFunctionA, '2'); // Argument of type 'string' is not assignable to parameter of type 'number'
callbackWrapper(callbackFunctionA, 2, 3); // Expected 2 arguments, but got 3.
callbackWrapper(callbackFunctionB, 2); // Expected 3 arguments, but got 2.

【讨论】:

    【解决方案2】:
    function callbackWrapper<T extends any[]>(
      callbackFunction: (...arg: T) => any,
      ...callbackFunctionProps: T
    ) {
      console.log(callbackFunction(...callbackFunctionProps));
    }
    
    function callbackFunction1(a: number) {
      return a + 2;
    }
    const callbackFunctionProps1 = 5;
    callbackWrapper(callbackFunction1, callbackFunctionProps1);
    
    function callbackFunction2(a: string) {
      return a + ' world';
    }
    const callbackFunctionProps2 = 'hello';
    callbackWrapper(callbackFunction2, callbackFunctionProps2);
    

    【讨论】:

    • 感谢重播!有没有办法不限制callbackFunctioncallbackFunctionProps的类型?让callbackWrapper 被任何函数和函数道具调用,并使打字稿验证给定的回调道具是否适合回调函数?甚至可能没有泛型,只是从使用中推断?
    • 嗯,知道了,你要把回调参数和传入的参数匹配
    猜你喜欢
    • 2021-11-18
    • 2021-12-15
    • 2021-03-31
    • 2021-01-22
    • 2012-11-30
    • 1970-01-01
    • 2018-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多