编程语言
首页 > 编程语言> > javascript – Typescript递归函数组合

javascript – Typescript递归函数组合

作者:互联网

我想创建一个函数链,它将是一个管道/流/组合函数的输入.

如果没有将类型的字面扩展到选定的深度,这是否可能,这通常是处理? See lodash’s flow.

我想实现链中数据流的类型检查.
  – 函数的参数是前一个函数的结果
  – 第一个参数是模板参数
  – 上次返回是模板参数

type Chain<In, Out, Tmp1 = any, Tmp2 = any> = [] | [(arg: In) => Out] | [(arg: In) => Tmp1, (i: Tmp1) => Tmp2, ...Chain<Tmp2, Out>];

这个想法在草案中.

然而,这会产生以下错误:

>类型别名’Chain’循环引用自身. (明白为什么,不知道如何解决)
> rest元素类型必须是数组类型. (可能传播不适用于通用元组)
>类型’链’不是通用的. (甚至不理解为什么这个错误甚至在这里)

在打字稿中这个链的定义是否可行?如果是这样,请附上一个片段.

(测试最新的tsc 3.1.6)

解决方法:

除某些情况外,实际上不支持循环类别别名.我没有尝试用TypeScript友好的方式来表示你在那里写的特定类型,而是我会将你的问题备份并解释为:我们如何键入一个类似于flow()的函数,它将其作为参数一个可变数量的单参数函数,其中每个单参数函数返回类型是下一个参数函数的参数类型,如链……并返回表示折叠链的单参数函数?

我有一些我认为有用的东西,但它很复杂,使用了很多conditional types,tuple spreadsmapped tuples.这里是:

type Lookup<T, K extends keyof any, Else=never> = K extends keyof T ? T[K] : Else
type Tail<T extends any[]> = 
  ((...t: T) => void) extends ((x: any, ...u: infer U) => void) ? U : never;
type Func1 = (arg: any) => any;
type ArgType<F, Else=never> = F extends (arg: infer A) => any ? A : Else;
type AsChain<F extends [Func1, ...Func1[]], G extends Func1[]= Tail<F>> =
  { [K in keyof F]: (arg: ArgType<F[K]>) => ArgType<Lookup<G, K, any>, any> };
type LastIndexOf<T extends any[]> =
  ((...x: T) => void) extends ((y: any, ...z: infer U) => void)
  ? U['length'] : never

declare function flow<F extends [(arg: any) => any, ...Array<(arg: any) => any>]>(
  ...f: F & AsChain<F>
): (arg: ArgType<F[0]>) => ReturnType<F[LastIndexOf<F>]>;

让我们看看它是否有效:

const stringToString = flow(
  (x: string) => x.length, 
  (y: number) => y + "!"
); // okay
const str = stringToString("hey"); // it's a string

const tooFewParams = flow(); // error

const badChain = flow(
  (x: number)=>"string", 
  (y: string)=>false, 
  (z: number)=>"oops"
); // error, boolean not assignable to number

对我来说看上去很好.

我不确定是否值得仔细阅读有关类型定义如何工作的详细信息,但我不妨解释如何使用它们:

>查找< T,K,Else>如果可以,尝试返回T [K],否则返回Else.所以Lookup< {a:string},“a”,数字>是字符串,查找< {a:string},“b”,数字>是号码.
> Tail< T>采用元组类型T并返回第一个元素被移除的元组.所以Tail< [“a”,“b”,“c”]>是[“b”,“c”].
> Func1只是单参数函数的类型.
> ArgType< F,Else>如果它是单参数函数,则返回F的参数类型,否则返回Else.所以ArgType<(x:string)=> number,boolean>是字符串,ArgType< 123,boolean>是布尔值.
> AsChain< F>获取一个单参数函数的元组并尝试将其转换为链,通过用下一个函数的参数类型替换F中每个函数的返回类型(并使用任何一个用于最后一个函数).如果AsChain< F>与F兼容,一切都很好.如果AsChain< F>与F不相容,那么F不是一个好的链.所以,AsChain< [(x:string)=> number,(y:number)=> boolean]>是[(x:string)=>数字,(y:数字)=>任何],这是好的.但是AsChain< [(x:string)=> number,(y:string)=> boolean]>是[(x:string)=> string,(y:string)=> any],这不好.
>最后,LastIndexOf< T>获取一个元组并返回最后一个索引,我们需要表示flow()的返回类型. LastIndexOf的百分比抑制率 “一”, “B”, “C”] GT;是2.

好的,希望有所帮助;祝好运!

标签:spread-syntax,function-composition,javascript,typescript,recursion
来源: https://codeday.me/bug/20191002/1843117.html