Этому сейчас четыре года, но мне удалось заставить печатную версию работать без перегрузок:
Необходима пара неприятных вещей:
Есть две причины, по которым нам нужны списки чисел:
- Учитывая определенный индекс, мы должны иметь возможность получить предыдущий индекс
- Нам нужно иметь возможность преобразовать строковые индексы кортежей в числовые индексы
type SNumbers = [
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15",
"16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31",
"32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47",
"48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63"];
type Numbers = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63];
// Util to prepend a value to a Tuple from: https://stackoverflow.com/a/54607819/5308589
type PrependTuple<A, T extends Array<any>> =
(((a: A, ...b: T) => void) extends (...a: infer I) => void ? I : [])
// Get the previous number (for indexing) (2=>1, 1=>0, 0=>never)
type PrevN<T extends number> = PrependTuple<never, Numbers>[T];
// Convert a string index to a number
type S_N<S extends SNumbers[number]> = {
[K in SNumbers[number]]: Numbers[K]
}[S]
Пара помощников:
Трубный / составной акт на одинарные функции
// Only unary functions wanted
type Unary = (i: any) => any;
// Get the (single) argument of a given unary function
type ParameterUnary<F extends Unary> = Parameters<F>["0"]
// ReturnType is a builtin
Основные типы:
UnariesToPiped / UnariesToComposed берет кортеж унарных функций и пытается сопоставить его кортежу, содержащему правильные типы функций
Затем Pipe / Compose просто использует сопоставленный кортеж в качестве аргумента и извлекает первый тип параметра и последний возвращаемый тип.
type UnariesToPiped<F extends Unary[]> = {
[K in keyof F]:
K extends SNumbers[number]
? K extends "0"
? F[K]
: (i: ReturnType<F[PrevN<S_N<K>>]>) => ReturnType<F[S_N<K>]>
: F[K]
}
type Pipe = <F extends Unary[]>(...funcs: UnariesToPiped<F>) => (i: ParameterUnary<F[0]>) => ReturnType<F[PrevN<F["length"]>]>
type UnariesToComposed<F extends Unary[]> = {
[K in keyof F]:
K extends SNumbers[number]
? K extends "0"
? F[K]
: (i: ParameterUnary<F[S_N<K>]>) => ParameterUnary<F[PrevN<S_N<K>>]>
: F[K]
}
type Compose = <F extends Unary[]>(...funcs: UnariesToComposed<F>) => (i: ParameterUnary<F[PrevN<F["length"]>]>) => ReturnType<F[0]>
Для примеров использования я опубликовал это на Github и NPM