简体   繁体   English

打字稿和(a,b)=> a + b

[英]Typescript and (a, b) => a+b

The following code doesn't compile (and I understand why): 以下代码无法编译(我理解原因):

let x: number[] = [];

x = ((a, b) => a+b)(x, x);
x.push(0);

This, however, compiles (and I don't understand why): 但是,这可以编译(我不明白为什么):

let x: number[] = [],
    f = (a, b) => a+b;

x = f(x, x);
x.push(0);

Then, if you run it, it produces a TypeError at runtime, like one would expect. 然后,如果您运行它,它将在运行时产生TypeError,就像人们期望的那样。

Why does Typescript handle these two samples differently? 为什么Typescript处理这两个样本的方式不同?

I guess I should make this an answer: 我想我应该把这个作为答案:

In this: 在此:

let x: number[] = [];
x = ((a, b) => a+b)(x, x);  // error
//             ~~~ <-- Operator '+' cannot be applied 
//                     to types 'number[]' and 'number[]'.
x.push(0);

The anonymous function (a, b) => a + b uses contextual typing to infer that both a and b are of type number[] , because you immediately apply it to parameters of that type. 匿名函数(a, b) => a + b使用上下文类型来推断ab均为number[]类型,因为您立即将其应用于该类型的参数。 And since you can't use the + operator on two arrays, you get an error. 而且由于不能在两个数组上使用+运算符,因此会出现错误。

On the other hand, in this: 另一方面,在此:

let x: number[] = [],
    f = (a, b) => a+b;  // f is (a: any, b: any) => any
x = f(x, x);
x.push(0);

The type of the value f is inferred by the compiler to be the type of (a, b) => a + b , and there are no contextual typing clues, since it is not being called at this point. 编译器将值f的类型推断为(a, b) => a + b ,并且没有上下文类型化线索,因为此时尚未调用它。 Yes, you call f(x, x) later, but typing doesn't flow backwards like that in general (contextual typing itself is sort of a very limited backward flow of typing). 是的,您稍后会调用f(x, x) ,但是打字不会像一般情况那样倒退(上下文打字本身是一种非常有限的倒退打字流程)。 After all, you could call f(x, x) and then f("hey", false) and then presumably the type of f would need to be some combination of both (a: number[], b: number[]) => any and (a: string, b: boolean) => string ? 毕竟,您可以先调用f(x, x) ,然后调用f(x, x) f("hey", false) ,然后假定f的类型需要是两者的某种组合(a: number[], b: number[]) => any(a: string, b: boolean) => string Or something else? 或者是其他东西? Who knows. 谁知道。 Instead, what actually happens is that the unannotated a and b parameters are inferred to be of type any . 相反,实际发生的情况是,未注释的ab参数被推断为any类型。 And since any effectively turns off the type system, a + b is not an error. 并且由于any有效地关闭了类型系统,所以a + b并不是错误。 The any type is insidious; any类型都是阴险的。 it tends to spread silently from one location to another in your program, and if you're not careful it can show up in places you don't expect. 它往往会在程序中从一个位置无声地传播到另一个位置,如果不小心,它可能会出现在您意想不到的地方。

The best way to combat this kind of thing is to enable the --noImplicitAny compiler option , which warns you when the compiler infers a type of any for something. 解决此类问题的最佳方法是启用--noImplicitAny 编译器选项 ,该选项会在编译器推断出某种类型的any时发出警告。 This way you should only have to worry about the any type when it has been explicitly written down in the code somewhere: 这样,您只需担心在某个地方的代码中明确写下来的any类型:

let x: number[] = [],
f = (a, b) => a+b;  // error
//   ~  ~ 
//      ^--- Parameter 'b' implicitly has an 'any' type.
//   ^------ Parameter 'a' implicitly has an 'any' type.

Now you can deal with that warning by deciding what you wanted a and b to be... presumably number : 现在,您可以通过确定ab含义来处理该警告……大概是number

let x: number[] = [],
f = (a: number, b: number) => a+b;  
x = f(x, x); // error
//    ~ <-- Argument of type 'number[]' is not assignable to parameter of type 'number'.

and then you will have to deal with trying to call f() on number[] arguments explicitly. 然后您将不得不尝试在number[]参数上显式调用f()

Okay, hope that helps. 好的,希望对您有所帮助。 Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM