使TypeScript推断高阶函数的模板参数

时间:2018-11-18 10:06:40

标签: typescript generics types inference

我有一些非常简单的函数,该函数接收一个函数和参数,并使用该参数执行该函数。 我写了这样的代码:

type Action<Payload> = (payload: Payload) => any;

type SomeType = string;

declare function execute<Payload>(action: Action<Payload>, payload: Payload);

declare function testFn<P extends SomeType>(payload: P): number;

execute(testFn, '');

run in typescriptlang.org repl

但是会产生错误:

Argument of type '<P extends string>(payload: P) => number' is not assignable to parameter of type 'Action<{}>'.
  Types of parameters 'payload' and 'payload' are incompatible.
    Type '{}' is not assignable to type 'string'.

事实是,如果我更改参数的顺序,它会使打字稿正确推断出类型:

type Action<Payload> = (payload: Payload) => any;

type SomeType = string;

declare function execute<Payload>(payload: Payload, action: Action<Payload>);

declare function testFn<P extends SomeType>(payload: P): number;

execute('hell yeah!', testFn);

run in typescriptlang.org repl

有没有一种方法可以使它在不更改订单的情况下工作?为什么打字稿总是尝试从左到右推断类型?

UPD:

它似乎是TypeScript本身中缺少的一部分:

PR with this feature added

same question on Github

huge discussion on the topic

1 个答案:

答案 0 :(得分:1)

这是一个有趣的问题。经过一番尝试之后,我认为我发现了一个具有正确行为的签名:

declare function execute<P>(action: Action<any> & Action<P>, payload: P): void;

相交类型似乎延迟了对Action<P>的求值,直到推断出P之后:

execute(testFn, '');  // okay
execute(testFn, 123);  // error, 123 is not a string

我真的不知道为什么会发生这种情况(也许更熟悉编译器内部的人可以在这里说些更好的话),但也许足以帮助您取得进步吗?祝你好运!

相关问题