TypeScript 中 <T>(a: T) => U 和 <a: T> => U 有什么区别

What's the difference of <T>(a: T) => U and <a: T> => U in TypeScript

如标题所述,如果我有一个函数声明如下:

applyTo<T, U>(a: T): (a: T) => U

调用函数:

applyTo(1)(x => x + '2')

TypeScript 会显示一个错误:

TS2345:Argument of type '(b: number) => number' is not assignable to parameter of type 'number'.

applyTo 函数的声明更改为以下代码,这将修复错误:

applyTo<T, U>(a: T): <T>(a: T) => U

不知道为什么?你能告诉我它们的区别吗?

缺少实现会使事情更清楚,但签名 ...

applyTo<T, U>(a: T): (a: T) => U

说:"Give me some T and I'll give you back a function that takes some other T as parameter and returns some U." 所以你应该将相同类型 T 的东西作为参数传递,例如:

applyTo(1)(2) // -> the result must be some U

由于在第一次调用中传递了一个数字作为参数,因此编译器需要另一个数字而不是来自 (x: whatever) => x + '2' 的函数。

第二个签名...

applyTo<T, U>(a: T): <T>(a: T) => U

可能会令人困惑,因为命名 T in (a: T) => U 不一定是相同类型的 T in (a: T): ...,所以如果每个参数和类型参数都有一个不同的名称会更好:

applyTo<T, U>(a: T): (b: T) => U
applyTo<T, U>(a: T): <S>(b: S) => U

现在第二个签名是:"Give me some T and I'll give back a function that takes some S as parameter and returns some U"

因此,根据实施情况,这将是有效的:

applyTo(1)        (x => x + '2')  =   ... 
//  ^^^^^^        ^^^^^^^^^^^^^^  
//  T is number   S is function       U is whatever;
//                from whatever to 
//                string