使用“类型“{}[]"的 TypeScript 拒绝不能分配给类型“数字" [英] TypeScript rejection with `Type '{}[]' is not assignable to type 'number'`

查看:41
本文介绍了使用“类型“{}[]"的 TypeScript 拒绝不能分配给类型“数字"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<代码>>让 f1: (x: number) =>数字 = x =>x * 2;>.type f1让 f1: (x: number) =>数字

如果我想取第一个值并将其翻倍,我可以这样做

let f2 = R.pipe( R.take(1), f1 );让 f2 = R.pipe( R.head, f1 );

这些都在 TypeScript 之外运行 f2([5,4,3]).然而,我得到了 TypeScript,

<代码>>让 f2 = R.pipe( R.take(1), f1 );[eval].ts(6,29): 错误 TS2345: '(x: number) => 类型的参数number' 不可分配给类型为 '(x: {}[]) => 的参数数字'.参数x"和x"的类型不兼容.类型{}[]"不可分配给类型数字".>让 f2 = R.pipe( R.head, f1 );[eval].ts(6,26): 错误 TS2345: '(x: number) => 类型的参数number' 不能分配给类型为 '(x: string) => 的参数数字'.参数x"和x"的类型不兼容.字符串"类型不能分配给数字"类型.

我做错了什么.我什至不知道如何阅读,

<块引用>

类型{}[]"不可分配给类型数字".

而且,我不明白是什么导致了

中的 string<块引用>

类型 'string' 不能分配给类型 'number'.

(我在任何地方都没有看到 string).

解决方案

这背后的普遍问题是 TypeScript 在处理高阶泛型函数时表现不佳:https://github.com/Microsoft/TypeScript/issues/9366.

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

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

//来自 ramda/index.d.tshead(列表:ReadonlyArray):T |不明确的;头(列表:字符串):字符串;

而且由于 TypeScript 还不能决定使用哪个重载(你既没有给它一个字符串也没有给它一个数组)它只是选择一个.根据我的经验,它选择最后定义的一个,更多细节在这里:https://github.com/Microsoft/TypeScript/issues/13570

为了使您的实例正常工作,您需要手动填写通用参数以使 TypeScript 停止做出错误的猜测:

let f4 = R.pipe(R.head, f1);

对于您使用 R.take(n) 的示例,根据 Ramda,即使输入它也不应该实际工作,因为它返回一个数组,而不是一个奇异值:

//来自 ramda/index.d.ts取<T>(n:数字):{(xs: 字符串): 字符串;(xs: ReadonlyArray): T[];};

Let's say I create a simple function to double its input,

> let f1: (x: number) => number = x => x * 2;
> .type f1
let f1: (x: number) => number

If I want to take the first value and double it, I can do either

let f2 = R.pipe( R.take(1), f1 );
let f2 = R.pipe( R.head, f1 );

Both of these work f2([5,4,3]) outside of TypeScript. However, with TypeScript I get,

> 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'.

What am I doing wrong. I'm not even sure how to read,

Type '{}[]' is not assignable to type 'number'.

and, I don't see what cause the string in

Type 'string' is not assignable to type 'number'.

(I don't see a string anywhere).

解决方案

The general issue behind this is that TypeScript does really poorly with higher-order generic functions: https://github.com/Microsoft/TypeScript/issues/9366.

In the majority of situations, when you pass a generic function (such as R.take(n) or R.head) into another (like R.pipe), instead of preserving free generic type parameters, TypeScript will automatically infer them. A lot of the time it infers these parameters as {}, its empty type.

In your second example with R.head, it infers string because R.head is actually defined with two overloads:

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

and since TypeScript can't decide yet which overload to use (you've given it neither a string nor an array) it just picks one. In my experience it picks the one defined last, more details on that here: https://github.com/Microsoft/TypeScript/issues/13570

To make your instances work, you're going to need to manually fill in the generic parameters to get TypeScript to stop making the wrong guesses:

let f4 = R.pipe<number[], number, number>( R.head, f1 );

For your example with R.take(n), according to Ramda it shouldn't actually work even if it typed, as it returns an array, not a singular value:

// from ramda/index.d.ts
take<T>(n: number): {
    (xs: string): string;
    (xs: ReadonlyArray<T>): T[];
};

这篇关于使用“类型“{}[]"的 TypeScript 拒绝不能分配给类型“数字"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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