下面的代码无法编译(我理解为什么):
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对这两个示例的处理方式不同?
下面的代码无法编译(我理解为什么):
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对这两个示例的处理方式不同?
1条答案
按热度按时间h5qlskok1#
在此:
匿名函数
(a, b) => a + b
使用上下文类型来推断a
和b
都是number[]
类型,因为您会立即将其应用于该类型的参数。由于您不能在两个数组上使用+
运算符,因此会得到错误。另一方面,在这方面:
值
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
的某种组合?或者其他什么?谁知道呢。相反,实际发生的是,未注解的a
和b
参数被推断为any
类型。由于any
有效地关闭了类型系统,因此a + b
不是错误。它往往悄悄地从程序中的一个位置传播到另一个位置,如果您不小心,它可能会出现在您不期望的地方。对付这种情况的最好方法是启用
--noImplicitAny
compiler option,当编译器推断出any
类型时,它会警告你。这样,你只需要担心any
类型,当它被显式地写在代码的某处时:现在,您可以通过决定您希望
a
和b
是什么来处理该警告......大概是number
:然后你将不得不处理试图在
number[]
参数上显式地调用f()
。