#typescript
#typescript
Вопрос:
Рассмотрим функцию:
const f = a => b => ... x => { return somevalue }
Как мне получить тип только для последней функции typeof x => { return somevalue }
, не зная общего количества замыканий?
Моя первоначальная мысль заключается в том, что нам нужно создать тип, который использует рекурсию и проверку условного типа, пока мы не дойдем до конца. Однако я не уверен, поддерживает ли typescript рекурсивные типы для такого рода задач.
Ответ №1:
Рекурсивные условные типы будут поддерживаться в TypeScript 4.1, когда он выйдет. На данный момент это доступно в typescript@next
. Тогда вы сможете написать что-то вроде
type LastFunc<T extends (...args: any) => any> =
T extends (...args: any) => infer R ?
R extends (...args: any) => any ? LastFunc<R> : T : never;
и использовать его в своей f
функции:
declare const somevalue: SomeValue;
const f = (a: any) => (b: any) => (c: any) => (d: any) => (x: any) => { return somevalue }
type LastFuncF = LastFunc<typeof f>; // type LastFuncF = (x: any) => SomeValue
Игровая площадка ссылка на код
До тех пор вы можете использовать либо неподдерживаемый обходной путь для получения такого поведения, например, следующую вещь с отложенным поиском объекта, которая сбивает с толку и раздражает:
type LastFunc<T extends (...args: any) => any> =
T extends (...args: any) => infer R ? {
0: LastFunc<Extract<R, (...args: any) => any>>, 1: T
}[R extends (...args: any) => any ? 0 : 1] : never
или вы можете использовать только поддерживаемые функции, разворачивая цикл до фиксированной глубины, что является избыточным и раздражающим:
type LastFunc<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R extends (...args: any) => any ? LF0<R> : T : never;
type LF0<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R extends (...args: any) => any ? LF1<R> : T : never;
type LF1<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R extends (...args: any) => any ? LF2<R> : T : never;
type LF2<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R extends (...args: any) => any ? LF3<R> : T : never;
type LF3<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R extends (...args: any) => any ? LF4<R> : T : never;
type LF4<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R extends (...args: any) => any ? LF5<R> : T : never;
type LF5<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R extends (...args: any) => any ? LF6<R> : T : never;
type LF6<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R extends (...args: any) => any ? LF7<R> : T : never;
type LF7<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R extends (...args: any) => any ? LF8<R> : T : never;
type LF8<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R extends (...args: any) => any ? LF9<R> : T : never;
type LF9<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R extends (...args: any) => any ? LFX<R> : T : never;
type LFX<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R extends (...args: any) => any ? R : T : never;
Игровая площадка ссылка на код
Лично я бы на вашем месте просто подождал до TS4.1. Хорошо, надеюсь, это поможет; удачи!