typescript 和(a,B)=>a+b

sxpgvts3  于 2023-03-24  发布在  TypeScript
关注(0)|答案(1)|浏览(122)

下面的代码无法编译(我理解为什么):

let x: number[] = [];

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

然而,这编译(我不明白为什么):

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

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

然后,如果你运行它,它会在运行时产生一个TypeError,就像人们所期望的那样。
为什么Typescript对这两个示例的处理方式不同?

h5qlskok

h5qlskok1#

在此:

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

匿名函数(a, b) => a + b使用上下文类型来推断ab都是number[]类型,因为您会立即将其应用于该类型的参数。由于您不能在两个数组上使用+运算符,因此会得到错误。
另一方面,在这方面:

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

f的类型被编译器推断为(a, b) => a + b的类型,并且没有上下文类型提示,因为此时没有调用它。是的,稍后会调用f(x, x),但是通常类型不会像那样向后流动(上下文类型本身是一种非常有限的反向类型)。毕竟,你可以先调用f(x, x),然后调用f("hey", false),然后假设f的类型需要是(a: number[], b: number[]) => any(a: string, b: boolean) => string的某种组合?或者其他什么?谁知道呢。相反,实际发生的是,未注解的ab参数被推断为any类型。由于any有效地关闭了类型系统,因此a + b不是错误。它往往悄悄地从程序中的一个位置传播到另一个位置,如果您不小心,它可能会出现在您不期望的地方。
对付这种情况的最好方法是启用--noImplicitAnycompiler option,当编译器推断出any类型时,它会警告你。这样,你只需要担心any类型,当它被显式地写在代码的某处时:

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

现在,您可以通过决定您希望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'.

然后你将不得不处理试图在number[]参数上显式地调用f()

相关问题