代码之家  ›  专栏  ›  技术社区  ›  alukach

验证是否可以使用同级参数调用参数(函数)

  •  1
  • alukach  · 技术社区  · 8 年前

    我正在编写一些高阶函数,发现很难编写类型来验证作为参数提供的函数是否可以使用提供的其他参数调用。下面是一个超级基本的例子:

    function(myFunc, arg1, arg2) {
        return myFunc(arg1, arg2) // We want to verify that this is typesafe at compile time
    }
    

    还有一个更现实的例子:

    // Here's a higher order function that returns a function that alters input in some way
    type algorithm = (input: number, options?: any) => number;
    const createHandler = (algorithm: algorithm, options?) =>
      (input: number) => algorithm(input, options);
    
    // This algorithm needs no 'options' configuration
    const addOne = (input) => input + 1;
    // This algorithm requires a specific 'options' configuration
    interface PowerOptions { value: number; }
    const power = (input: number, {value}: PowerOptions) => input ** value
    
    // Now when I create these handlers, I'd like for the 'options' to be validated against the provided function
    const addOneHandler = createHandler(addOne);
    const squaredHandler = createHandler(power, { value: 2 });
    const cubedHandler = createHandler(power, {});  // This should show a type error as the options are invalid for the algorithm
    
    1 回复  |  直到 8 年前
        1
  •  1
  •   arvymetal    8 年前

    关于您的基本示例,您可以通过类型推断以这种方式来检查所提供函数的类型安全性。( check it on Typescript Playground ):

    const a = function <U, V>(myFunc: (arg1: U, arg2: V) => any, arg1: U, arg2: V) {
        return myFunc(arg1, arg2)
    }
    
    const doubleIfTrue = (arg1: number, arg2: boolean) => arg2 ? 2 * arg1 : arg1
    
    console.log(a(doubleIfTrue, 1, true))  // Type OK
    console.log(a(doubleIfTrue, 1, "hop")) // Wrong type: number and string provided
    

    在这种情况下, U V 根据所提供函数的参数推断类型。


    但是你想要达到的目标会变得更加复杂。根据你的代码,我可以解决一些问题( check it on Typescript Playground ):

    type algorithm<OPT = null> = (input: number, options?: OPT) => number;
    type algorithmOptions<A> = A extends algorithm<infer OPT> ? OPT : null
    
    const createHandler = <A extends algorithm<any>>(algorithm: A, options: algorithmOptions<A>) =>
    (input: number) => algorithm(input, options);
    
    // Algorithms
    const addOne:algorithm = (input: number) => input + 1;
    interface PowerOptions { value: number; }
    const power:algorithm<PowerOptions> = (input: number, {value}) => input ** value
    
    // Handlers
    const squaredHandler = createHandler(power, { value: 2 }); // correct
    const addOneHandler = createHandler(addOne, null); // correct if a second argument is provided
    
    const addOneHandlerFailing = createHandler(addOne, { value: 2 }); // wrong because an argument is provided
    const squaredHandlerFailing1 = createHandler(power, {}); // wrong because of argument interface not respected
    const squaredHandlerFailing2 = createHandler(power); // wrong because no argument provided
    

    有一些 conditional type 检索算法参数。但也许我走得太远了,你可以找到一个更简单的方法

    另一件事:据我所知,似乎 createHandler 在某些情况下不能是可选的,而在另一些情况下则是强制的,这样就不会使示例变得更复杂。

    希望有帮助!

    推荐文章