如何使用参数转发来注释高阶函数

How to annotate high order function with arguments forwarding

我正在尝试为这篇作文添加注释:

const get1 = (n: number, s: string) => `${n}_${s}`;
const get2 = (s: string, n: number) => `${n}_${s}`;

const foo = (get) => (...args) => {
    get(...args);
}

const foo1= foo(get1);
const foo2= foo(get2);


foo1(2, 'qwe');
foo2('qwe', 1)

目前我正在使用 Flow 作为类型检查器,但我也对 TypeScript 答案感兴趣,因为它可能是我迁移的好点。

以下是您可以在此示例中使用的方法:

const get1 = (n: number, s: string) => `${n}_${s}`;
const get2 = (s: string, n: number) => `${n}_${s}`;

const foo = <T extends any[], R>(get: (...args: T) => R) => (...args: T): R => {
  return get(...args);
};

const foo1 = foo(get1);
const foo2 = foo(get2);

foo1(2, "qwe");
foo2("qwe", 1);

TypeScript Playground

如果您是 TypeScript 的新手,此示例依赖于 Generics and Rest Parameters. Specifically, Rest Generics in this example were added in 3.0

提出以下解决方案:

// @flow

const get1 = (n: number, s: string) => `${n}_${s}`;
const get2 = (s: string) => `_${s}`;

type Apply<T, R> = (...args: T) => R

const foo = <TArgs: *>(get: Apply<TArgs, string>): Apply<TArgs, Promise<*>> =>
    (...args) => {
        const str = get(...args);

        return Promise.resolve(str);
    }


const foo1= foo(get1);
const foo2= foo(get2);


foo1(1, 'qwe');
foo2('qwe');

// $ExpectError      
foo2('qwe', 'qwer') //wrong arity
// $ExpectError 
foo2('qwe', 2, 3, 5, 6, 4) //wrong arity
// $ExpectError 
foo1(1, 'qwe', 3, 5, 6) //wrong arity

这个例子还有一个补充,我没有返回 get 的结果,而是在函数内部使用它。

看起来它几乎可以正常工作。缺少的一件事是 foo1 和 foo2 的参数。但至少类型检查工作正常

感谢大家的回答

这里是流程版本:

const get1 = (n: number, s: string) => `${n}_${s}`;
const get2 = (s: string, n: number) => `${n}_${s}`;

const foo = <A: mixed[], R>(get: (...A) => R): ((...A) => R) => 
  (...args: A): R =>
    get(...args);

const foo1= foo(get1);
const foo2= foo(get2);


foo1(2, 'qwe');
foo2('qwe', 1);
// $ExpectError
foo1('qwe', 2);
// $ExpectError
foo2(2, 'qwe');

foo2('qwe', 1, 3); // this should probably error but doesn't

(Try)