Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
没有重载的Typescript中的函数组合_Typescript_Types_Pipe_Flow_Function Composition - Fatal编程技术网

没有重载的Typescript中的函数组合

没有重载的Typescript中的函数组合,typescript,types,pipe,flow,function-composition,Typescript,Types,Pipe,Flow,Function Composition,是否可以为函数组合定义Typescript类型(请参阅或) 对于任意数量的参数(要编写的函数)没有覆盖,但能够提示类型 如果没有类型推断,我的上一个 但是,此解决方案仅在显式定义类型时验证链并报告错误: const badChain=flow( (x:number)=>“字符串”, (y:string)=>false, (z:number)=>“哎呀” ); // 错误,布尔值不可分配给数字 但所有的论点都是错误的 流( (x:number)=>“字符串”, (y:string)=>false

是否可以为函数组合定义Typescript类型(请参阅或) 对于任意数量的参数(要编写的函数)没有覆盖,但能够提示类型

如果没有类型推断,我的上一个

但是,此解决方案仅在显式定义类型时验证链并报告错误:

const badChain=flow(
(x:number)=>“字符串”,
(y:string)=>false,
(z:number)=>“哎呀”
); // 错误,布尔值不可分配给数字
但所有的论点都是错误的

流(
(x:number)=>“字符串”,
(y:string)=>false,
z=>{/*z为任意值,但应推断为布尔值*/}
);
这个推论适用于lodash和ramda类型,但它的定义是使用长度不可维护的重载,正如我在前面的问题中所述


有没有办法避免并且不丢失类型推断?

没有办法删除所有重载。类型
R*
参数相互依赖的方式目前在类型系统中无法表达

我们可以做的一个改进是,不需要在第一个函数(添加
A*
类型参数的函数)上添加额外参数的重载。这可以在3.0中使用

接口静态{
流量(f1:(…a:a)=>R1,f2:(a:R1)=>R2:(…a:a)=>R2;
流量(f1:(…a:a)=>R1,f2:(a:R1)=>R2,f3:(a:R2)=>R3:(…a:a)=>R3;
流量(f1:(…a:a)=>R1,f2:(a:R1)=>R2,f3:(a:R2)=>R3,f4:(a:R3)=>R4:(…a:a)=>R4;
流量(f1:(…a:a)=>R1,f2:(a:R1)=>R2,f3:(a:R2)=>R3,f4:(a:R3)=>R4,f5:(a:R4)=>R5:(…a:a)=>R5;
流量(f1:(…a:a)=>R1,f2:(a:R1)=>R2,f3:(a:R2)=>R3,f4:(a:R3)=>R4,f5:(a:R4)=>R5,f6:(a:R5)=>R6:(…a:a)=>R6;
流量(f1:(…a:a)=>R1,f2:(a:R1)=>R2,f3:(a:R2)=>R3,f4:(a:R3)=>R4,f5:(a:R4)=>R5,f6:(a:R5)=>R6,f7:(a:R6)=>R7:(…a:a)=>R7;
}
声明常量:LoDashStatic;
设f=u0;.flow((n:number,s:string)=>n+s,o=>o.toUpperCase());//f:(n:number,s:string)=>string

可能不太清楚为什么仍然需要重载。我使用了各种实现,找到了我认为的问题的核心,至少给出了一种方法,它解决了自下而上枚举所有链的问题(这比重载稍微好一点,因为您可以自引用较低的级别),并且您仍然应该得到类型推断

const a: [(_: string) => number, (_: number) => boolean] | [(_: string) => boolean] = [x => x.length, y => true]
只需重载即可通过元组的长度检测元组。TS可以通过重载(根据参数的数量选择签名)来管理它,但对于没有函数签名的纯元组,TS无法做到这一点。这就是为什么在代码段中没有推断出
y
,也就是为什么在当前状态下如果没有重载,使解决方案更紧凑的努力就无法成功


因此,认可的答案似乎是目前最好的解决方案

这已经四年了,但我成功地让一个类型化版本在没有重载的情况下工作:

需要做一些令人讨厌的事情:

我们需要数字列表有两个原因:

  • 给定一个特定的索引,我们需要能够检索以前的索引
  • 我们需要能够将严格的元组索引转换为数字索引
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"];
类型编号=[
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将值前置到元组,从:https://stackoverflow.com/a/54607819/5308589

键入PrependTuple和

Nope,这是目前唯一的方法。唯一的改进可能是不覆盖多个参数(删除A1…AN重载只保留一个集)。
const a: [(_: string) => number, (_: number) => boolean] | [(_: string) => boolean] = [x => x.length, y => true]
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
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]>