Вывод типа функции более высокого порядка при удалении первого параметра не работает - PullRequest
0 голосов
/ 04 апреля 2020

У меня есть функция, которая, учитывая другую функцию и список аргументов, вызывает эту функцию, предоставляет первый аргумент и пересылает список заданных аргументов, начиная со второго (в некоторой степени похож на bind). Затем возвращается результат данного аргумента.

Вызов

foo(anotherFunction, 1, '2');

вызовет anotherFunction примерно так:

anotherFunction(someValue, 1, '2');

Проблема возникает с выводом типа, когда функция имеет параметр типа. Взгляните на этот код:

// First attempt to type foo
declare function foo1<A extends any[], R>(
    fn: (arg1: any, ...args: A) => R,
    ...args: A
): R;

// Type of foo with the specific case the second parameter is a function
declare function foo2<A2 extends any[], R2, A extends any[], R>(
    fn: (arg1: any, arg2: (...args: A2) => R2, ...args: A) => R,
    arg2: (...args: A2) => R2,
    ...args: A
): R;

declare function bar<T>(a: number, fn: (a: number) => T): T;

// `result1: string`, OK
const result1 = bar(1, x => x.toString());
// ERROR: 'x' implicitly has an 'any' type
const result2 = foo1(bar, x => x.toString());
// No error and `result3: string`, OK but requires type annotation
const result3 = foo1(bar, (x: number) => x.toString());
// No errors but `result4: unknown`, not Ok (*)
const result4 = foo2(bar, x => x.toString());
// `result5: string`, OK but requires type annotation
const result5 = foo2(bar, (x: number) => x.toString());

Playground Link

Функция foo1 и foo2 - это два способа ввода функции foo, и bar - это функция, которая будет вызываться fooX. В целом foo1 работает хорошо, но не делает хорошего вывода, если некоторые из приведенных аргументов являются функцией с параметрами типа. Функция foo2 учитывает конкретный случай c, что вторым аргументом является функция, которая работает немного лучше, но не совсем.

Вопрос1: Есть ли способ напишите такую ​​функцию, учитывая, что любой аргумент может быть функцией? Случай, когда второй параметр является функцией, для меня гораздо более распространен, поэтому решение, учитывающее только это, все еще работает.

Идея состоит в том, что параметры функций, указанные в списке аргументов, будут выводиться без необходимости явной аннотации типа (или, по крайней мере, для первого аргумента, если это функция).

Вопрос2: Почему result4 выводится как unknown, даже когда x (параметр функции, строка, отмеченная (*)) правильно выводится как number?


РЕДАКТИРОВАНИЕ:

Я только что понял, что .bind() также удаляет параметр типа:

declare function bar<T>(a: number, fn: (a: number) => T): T;

// boundBar: (fn: (a: number) => unknown) => unknown
const boundBar = bar.bind(undefined, 0);

// result1: unknown
const result1 = boundBar(x => x.toString());

Playground Link

Я думал, https://github.com/microsoft/TypeScript/pull/30215 здесь поможет, но, может быть, я был не прав.

Это ошибка или ограничение дизайна?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...