试图用TypeScript弄湿我的脚,我一直遇到麻烦。今天,一个旧功能浮出水面,并且作为练习,我很好奇是否可以将其转换为TypeScript。到目前为止,颈部已经完全疼痛。
declare type Ord = number | string;
// type signature for f sucks really bad
// (f: Ord => Ord => boolean) would be really nice, if possible
// but instead I have to give names (_) for the parameters? dumb
const arrayCompare = (f: (_: Ord) => (_: Ord) => boolean) => ([x,...xs]: Ord[]) => ([y,...ys]: Ord[]): boolean => {
if (x === undefined && y === undefined)
return true;
else if (! f (x) (y))
return false;
else
return arrayCompare (f) (xs) (ys);
}
// here the names of the parameters are actually used
const eq = (x: Ord) => (y: Ord) : boolean => x === y;
// well at least it works, I guess ...
console.log(arrayCompare (eq) ([1,2,3]) ([1,2,3])); // true
console.log(arrayCompare (eq) (['a','b','c']) (['a','b','c'])); // true
因此,问题特别是关于(请参阅粗体)
const arrayCompare = (f: (_: Ord) => (_: Ord) => boolean) => ...
f
期望该类型的高阶函数
Ord => Ord => boolean
但是如果我使用这种类型签名
// danger !! unnamed parameters
(f: (Ord) => (Ord) => boolean)
TypeScript将假定Ord
为参数名称,并且隐式类型为any
// what TypeScript thinks it means
(f: (Ord: any) => (Ord: any) => boolean)
当然,这不是我想要的,但这仍然是我得到的。为了得到我真正想要的,我必须为高阶函数指定参数的名称
// now it's correct
(f: (_: Ord) => (_: Ord) => boolean)
但这没什么意义。f
在这种情况下,我只能访问,而在f
最终调用它时将无法访问将绑定的参数...
题
为什么必须在TypeScript中为高阶函数参数提供名称?
这没有任何意义,并且会使函数签名冗长,丑陋,难于编写和难于阅读。
更新
“就参数名称而言,请考虑采用->(数字->数字->数字)->的回调的函数,因此,仅基于您选择的类型:加,减,乘,除,幂,比较其中只有一个是有意义的,现在,如果回调参数具有名称添加:(数字->数字->数字),选择将显而易见” – Aleksey Bykov
我很高兴有机会对此进行回复。我可以用(number -> number -> number)
签名命名更多的函数。
first
,second
,mod
,min
,max
&
,|
,xor
,<<
,和>>
(x, y) => sqrt(sq(x) + sq(y))
(x, y) => x + x + y + y + superglobalwhocares
为了清楚起见,我不建议不要给函数参数本身起一个名字。我建议不要给函数参数的参数起个名字...
// this
func = (f: (number => number => number)) => ...
// not this
func = (f: (foo: number) => (bar: number) => number)) => ...
为什么?很好,因为f
不了解我将要提供的功能参数。
// for the record, i would never name parameters like this
// but for those that like to be descriptive, there's nothing wrong with these
const add = (addend: number) => (augend: number) => number ...
const sub = (minuend: number) => (subtrahend: number) => number ...
const divide = (dividend: number) => (divisor: number) => number ...
const mult = (multiplicand: number) => (multiplier: number) => number ...
// I could use any of these with my func
func (add ...)
func (sub ...)
func (divide ...)
func (mult ...)
如果尝试过,我将无法提供f
参数的名称func
!因为谁知道我将使用哪个功能?所有这些都是适当的。
如果我尝试在其上加上名称,则会使用户无法想象功能的功能。
// maybe the user thinks only a division function can be specified (?)
func = (f: (dividend: number) => (divisor: number) => number) => ...
dividend
而divisor
不是一个不错的选择这里,是因为上面列出的任何功能将适合。在最好的我能做到这一点
// provide generic name for f's parameters
func = (f: (x: number) => (y: number) => number) => ...
但是那有什么意义呢?它不像x
并y
成为绑定标识符。并且x
,y
没有提供任何附加说明-我想让我明白我的意思:它们并不具有名称或说明。具有零的我们可能会使用它的方式的知识,但它并不重要; 只要有接口,这就是我们关心的全部。这就是我们可以向用户提供有关参数的最有用的信息。f
(number => number => number)
func
f
“对于这样的功能,这将非常令人困惑:
foo(cb: (number, number) => (number, string) => boolean)
它是做什么的?” -工会
此处使用相同的确切推理。除了(cb: (number, number) => (number, string) => boolean))
功能设计不佳的事实(您可以命名几个有用的混合类型四元(4- arity)函数?)外,这也没有关系。f
不能假装知道使用此类签名可以提供的无数函数的任何描述符。
所以我的问题是,为什么我必须为函数参数参数指定明显无意义的名称?
行使
您可以_
用有意义的名称代替吗?
const apply2 = (f: (_: number) => (_: number) => number) => (x: number) => (y: number): number => {
return f (x) (y)
};
const sqrt = (x: number): number => Math.sqrt(x);
const sq = (x: number): number => x * x;
const add = (addend: number) => (augend: number): number => addend + augend;
const pythag = (side1: number) => (side2: number): number => sqrt(add(sq(side1)) (sq(side2)));
console.log(apply2 (add) (3) (4)); // 7
console.log(apply2 (pythag) (3) (4)); // => 5
如果不是,您能否提出令人信服的论点,为什么在TypeScript签名中必须出现这样的名称?
至少以易读的方式很难编写易变的定义。
我要做的是尽可能地在函数声明之外提取签名,如下所示:
type Ord = string | number;
type ThirdFunction = (objs: Ord[]) => boolean;
type SecondFunction = (objs: Ord[]) => ThirdFunction;
type FirstFunction = (fn: (o: Ord) => (o: Ord) => boolean) => SecondFunction;
const arrayCompare: FirstFunction = f => ([x,...xs]) => ([y,...ys]) => {
...
}
(操场上的代码)
我还删除了declare
您在Ord
类型别名之前使用的,因此不需要它。您可以为这些类型找到更好的名称。
另一件事是,您无需在boolean
此处指定:
const eq = (x: Ord) => (y: Ord) : boolean => x === y;
可:
const eq = (x: Ord) => (y: Ord) => x === y;
或者,您可以使用单个type
声明来表达该功能。考虑到所有因素,可读性相当不错。
type Ord = number | string;
type arrayCompareFunc = (f: (x: Ord) => (y: Ord) => boolean)
=> (xs: Ord[])
=> (ys: Ord[])
=> boolean;
const arrayCompare: arrayCompareFunc = f => ([x,...xs) => ([y,...ys) => {
...
};
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句