我是否必须为TypeScript中的高阶函数类型指定参数名称? [英] Do I have to specify parameter names for higher-order function types in TypeScript?

查看:88
本文介绍了我是否必须为TypeScript中的高阶函数类型指定参数名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试使用TypeScript弄湿我的脚,但我一直遇到麻烦. 旧功能今天浮出水面,并且作为练习,我很好奇是否可以将其转换为TypeScript.到目前为止,颈部已经完全疼痛.

Trying to get my feet wet using TypeScript and I keep running into trouble. An old function resurfaced today and just as an exercise, I was curious if I could convert it to TypeScript. So far it's been a complete pain in the neck.

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

所以这个问题专门针对(请参阅粗体)

So the question is specifically about (see bold)

const arrayCompare = (f: (_: Ord) => (_: Ord) => boolean) => ...

f期望该类型的高阶函数

f is expecting a higher-order function of the type

Ord => Ord => boolean

但是如果我使用这种类型签名

But if I use this type signature

// danger !! unnamed parameters
(f: (Ord) => (Ord) => boolean)

TypeScript将Ord作为参数的 name ,并且隐含类型为any

TypeScript will assume Ord as the name of the parameter and the implied type is any

// what TypeScript thinks it means
(f: (Ord: any) => (Ord: any) => boolean)

当然,这不是我想要的,但是无论如何,这就是我得到的.为了得到我真正想要的,我必须为高阶函数指定参数的名称

Of course this is not what I want, but that's what I get anyway. In order to get what I actually want, I have to specify the names of the parameters for the higher-order function

// now it's correct
(f: (_: Ord) => (_: Ord) => boolean)

但是来吧,这没有任何意义.在这种情况下,我只能访问f,而在我最终调用它时不能访问f将绑定的参数...

But c'mon that makes no sense. I only have access to f in this context, not to the parameters that f will bind when I eventually call it...

问题

为什么必须为TypeScript中的高阶函数参数提供名称?

Why do I have to provide names for higher-order function parameters in TypeScript?

这毫无意义,并使函数签名冗长,丑陋,难于编写和阅读.

It makes no sense and makes the function signatures long, ugly, harder to write, and harder to read.

更新

"作为参数的名称,请考虑采用->回调的函数. (数字->数字->数字)->,因此仅基于类型,您的选择是:加,减,乘,除,乘方,比较,只有一个才有意义,现在,如果回调参数具有名称添加:(数字->数字->数字)选择将是显而易见的".很高兴能有机会对此进行回复.我可以使用(number -> number -> number)签名来命名更多的函数.

I'm happy to be given an opportunity to reply to this. I can name heaps more functions with (number -> number -> number) signature.

  • firstsecondmodminmax
  • 按位函数&|xor<<>>
  • (x, y) => sqrt(sq(x) + sq(y))
  • (x, y) => x + x + y + y + superglobalwhocares
  • 您可以梦想的
  • 任何其他功能
  • first, second, mod, min, max
  • bitwise functions &, |, xor, <<, and >>
  • (x, y) => sqrt(sq(x) + sq(y))
  • (x, y) => x + x + y + y + superglobalwhocares
  • and any other function you can dream up

为澄清起见,我不建议不要给函数参数本身起一个名字.我建议不要给函数参数的 parameters 指定名称...

To clear things up, I'm not suggesting the function parameter itself should not be given a name. I'm suggesting that function parameter's parameters should not be given names ...

// this
func = (f: (number => number => number)) => ...

// not this
func = (f: (foo: number) => (bar: number) => number)) => ...

为什么?很好,因为f不了解我将要提供的功能的参数.

Why? well because f has no knowledge of the parameters of the function that I will be providing.

// 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 ...)

如果尝试,我将无法在func中提供f参数的名称!因为谁知道我将使用哪个功能?所有这些都是合适的.

I couldn't provide names for f's parameters in func if I tried ! Because who knows which function I will use? All of them are appropriate.

如果我尝试在其上加上名称,则会使用户无法想象该功能可以实现的功能...

If I try to put names on them, I pigeonholed the user's imagination of what the function is capable of ...

// maybe the user thinks only a division function can be specified (?)
func = (f: (dividend: number) => (divisor: number) => number) => ...

dividenddivisor在这里不合适,因为上面列出的任何功能都适用.在最佳,我可以做到

dividend and divisor are not a good fit here because any of the functions listed above would fit. At best I could do this

// provide generic name for f's parameters
func = (f: (x: number) => (y: number) => number) => ...

但是那有什么意义呢?并不是xy成为绑定标识符.而且xy没有提供附加的描述-我想这使我想到了 :它们不是 meant 的名称或描述. f对我们可能会使用它的方式有 zero 的知识,但这无关紧要;只要它具有(number => number => number)接口,那就是我们所关心的 all .这就是我们可以为func用户提供的与f参数有关的有用信息.

But then what's the point? It's not like x and y become bound identifiers. And x and y offer no added description – which I suppose brings me to my point: they're not meant to have a name or description. f has zero knowledge of the way we might use it, but it doesn't matter; as long as it has a (number => number => number) interface, that's all we care about. And that's the most useful information we can provide to the user of our func regarding the f parameter.

"对于类似这样的函数,这将非常令人困惑:

foo(cb: (number, number) => (number, string) => boolean)

它是做什么的?" -统一

此处也适用相同的确切推理.除了(cb: (number, number) => (number, string) => boolean))是一个设计不良的函数(您可以命名几个有用的混合类型四元(4-arity)函数?)这一事实之外,没关系. f不能假装知道使用此类签名可以提供的无数函数的任何描述符.

Same exact reasoning applies here. Besides the fact that (cb: (number, number) => (number, string) => boolean)) is a poorly-designed function (how many useful mixed-type quaternary (4-arity) functions can you name?), it doesn't matter. f can't pretend to know any descriptors about the countless functions I could come up with that use such a signature.

所以我的问题是,为什么我要为函数参数 parameters 毫无意义地指定公开无意义的名称?

So my question is, why the heck do I have to specify overtly meaningless names for function parameter parameters ?

锻炼

您可以用有意义的名称替换_吗?

Can you replace _ with meaningful names?

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签名中必须出现这样的名称?

If not, can you make a compelling argument why such names must be present in your TypeScript signature?

推荐答案

至少要以可读的方式编写难以理解的定义.
我要做的是尽可能地在函数声明之外提取签名,就像这样:

It's hard to write currying definitions, at least in a way that is readable.
I would do is to extract the signatures outside of the function declaration as much as possible, something like this:

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]) => {
    ...
}

(我还删除了Ord类型别名之前的declare,所以不需要它.您可以找到更好的类型名称.
另一件事是,您无需在此处指定boolean:

I also removed the declare you had before the Ord type alias, there's no need for it. And you can find better names for the types.
Another thing is that you don't need to specify the boolean here:

const eq = (x: Ord) => (y: Ord) : boolean => x === y;

可以是:

const eq = (x: Ord) => (y: Ord) => x === y;


或者您可以使用单个type声明来表达该功能.考虑到所有因素,可读性相当不错.


Or you could express the function using a single type declaration. Readability is fairly decent, all things considered.

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) => {
   ...
};

这篇关于我是否必须为TypeScript中的高阶函数类型指定参数名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆