Typescript 带有“Type'”的打字脚本拒绝;{}[]和#x27;不可分配给类型';编号'`

Typescript 带有“Type'”的打字脚本拒绝;{}[]和#x27;不可分配给类型';编号'`,typescript,typescript-typings,ramda.js,definitelytyped,Typescript,Typescript Typings,Ramda.js,Definitelytyped,假设我创建了一个简单的函数,将其输入加倍 > let f1: (x: number) => number = x => x * 2; > .type f1 let f1: (x: number) => number 如果我想取第一个值并将其加倍,我可以选择 let f2 = R.pipe( R.take(1), f1 ); let f2 = R.pipe( R.head, f1 ); 这两项工作都是在TypeScript之外进行的。然而,我得到了TypeScri

假设我创建了一个简单的函数,将其输入加倍

> let f1: (x: number) => number = x => x * 2;
> .type f1
let f1: (x: number) => number
如果我想取第一个值并将其加倍,我可以选择

let f2 = R.pipe( R.take(1), f1 );
let f2 = R.pipe( R.head, f1 );
这两项工作都是在TypeScript之外进行的。然而,我得到了TypeScript

> let f2 = R.pipe( R.take(1), f1 );
[eval].ts(6,29): error TS2345: Argument of type '(x: number) => number' is not assignable to parameter of type '(x: {}[]) => number'.
  Types of parameters 'x' and 'x' are incompatible.
    Type '{}[]' is not assignable to type 'number'.

> let f2 = R.pipe( R.head, f1 );
[eval].ts(6,26): error TS2345: Argument of type '(x: number) => number' is not assignable to parameter of type '(x: string) => number'.
  Types of parameters 'x' and 'x' are incompatible.
    Type 'string' is not assignable to type 'number'.
我做错了什么。我甚至不知道怎么读

而且,我看不出是什么原因导致了
字符串


(我在任何地方都看不到
字符串)。

这背后的一般问题是,TypeScript在使用高阶泛型函数时做得很差:

在大多数情况下,当您将一个泛型函数(如
R.take(n)
R.head
)传递到另一个函数(如
R.pipe
)时,TypeScript将自动推断它们,而不是保留自由的泛型类型参数。很多时候,它将这些参数推断为
{}
,它是空类型

在使用
R.head
的第二个示例中,它推断字符串,因为
R.head
实际上是用两个重载定义的:

// from ramda/index.d.ts
head<T>(list: ReadonlyArray<T>): T | undefined;
head(list: string): string;

这背后的一般问题是,TypeScript在使用高阶泛型函数时表现非常糟糕:

在大多数情况下,当您将一个泛型函数(如
R.take(n)
R.head
)传递到另一个函数(如
R.pipe
)时,TypeScript将自动推断它们,而不是保留自由的泛型类型参数。很多时候,它将这些参数推断为
{}
,它是空类型

在使用
R.head
的第二个示例中,它推断字符串,因为
R.head
实际上是用两个重载定义的:

// from ramda/index.d.ts
head<T>(list: ReadonlyArray<T>): T | undefined;
head(list: string): string;

你说到了每一点,我真的很喜欢你把github问题联系起来。回答得很好。事实上,我很想知道为什么
take(1)
也是这样工作的(我可能会要求跟进,因为我对那里的历史有点感兴趣)。我将在这一个上掷下一个悬赏(并在稍后将其标记为已接受),以帮助您通过堆栈溢出的等级。别动!你认为flow能更好地处理这个问题吗?我对Flowtype没有太多的经验或知识,但它确实能正确地处理这个问题。最近合并了一个PR,这可能会使TypeScript在将来更好地推断这些类型:你抓住了每一点,我真的很喜欢你将github问题联系起来。回答得很好。事实上,我很想知道为什么
take(1)
也是这样工作的(我可能会要求跟进,因为我对那里的历史有点感兴趣)。我将在这一个上掷下一个悬赏(并在稍后将其标记为已接受),以帮助您通过堆栈溢出的等级。别动!你认为flow能更好地处理这个问题吗?我对Flowtype没有太多的经验或知识,但它确实能正确地处理。最近合并了一个PR,这可能会使TypeScript在将来更好地推断这些类型:
// from ramda/index.d.ts
head<T>(list: ReadonlyArray<T>): T | undefined;
head(list: string): string;
let f4 = R.pipe<number[], number, number>( R.head, f1 );
// from ramda/index.d.ts
take<T>(n: number): {
    (xs: string): string;
    (xs: ReadonlyArray<T>): T[];
};