为什么 TypeScript 有 `void` 和 `undefined`? [英] Why does TypeScript have both `void` and `undefined`?
问题描述
在 TypeScript 中,您可以将函数注释为返回 void
:
In TypeScript, you can annotate a function as returning void
:
function fn1(): void {
// OK
}
function fn2(): void {
// Error
return 3;
}
你也可以注释一个函数返回undefined
:
You can also annotate a function to return undefined
:
function fn3(): undefined {
// OK
return;
}
function fn4(): undefined {
// Error
return 3;
}
所以看起来如果你调用一个返回 void
的函数,你总是会得到 undefined
的值.但是你不能写这个代码:
So it seems that if you call a function returning void
, you'll always get back the value undefined
. Yet you can't write this code:
function fn5(): void {
}
let u: undefined = fn5(); // Error
为什么 void
不只是 undefined
的别名?它需要存在吗?
Why isn't void
just an alias for undefined
? Does it need to exist at all?
推荐答案
void
在函数返回类型中具有特殊意义,不是 undefined
的别名.这种想法是非常错误的.为什么?
void
has special meaning in function return types, and is not an alias for undefined
. Thinking of it this way is very wrong. Why?
void
的目的是不会观察到函数的返回值.这与将undefined
非常不同.区分这一点很重要,这样您就可以正确地描述像 forEach
这样的函数.让我们考虑一个独立版本的 Array#forEach
,在回调返回位置用 undefined
而不是 void
编写:
The intent of void
is that a function's return value will not be observed. This is very different from will be undefined
. It's important to have this distinction so that you can properly describe functions like forEach
. Let's consider a freestanding version of Array#forEach
, written with undefined
instead of void
in the callback return position:
declare function forEach<T>(arr: T[], callback: (el: T) => undefined): void;
如果您尝试使用此功能:
If you tried to use this function:
let target: number[] = [];
forEach([1, 2, 3], el => target.push(el));
你会得到一个错误:
输入数字"不可分配给类型未定义"
Type "number" is not assignable to type "undefined"
这是一个正确的错误 - 你说你想要一个返回值 undefined
的函数,但你实际上提供了一个返回值 number
的函数,因为这就是为什么 Array#push
返回!
This is a correct error - you said you wanted a function that returned the value undefined
, but you actually provided a function that returned the value number
because that's why Array#push
returns!
使用 void
代替意味着 forEach
承诺不使用返回值,因此可以使用返回任何值的回调调用它
Using void
instead means that forEach
promises not to use the return value, so it can be called with a callback that returns any value
declare function forEach<T>(arr: T[], callback: (el: T) => void): void;
let target: number[] = [];
// OK
forEach([1, 2, 3], el => target.push(el));
为什么不直接使用 any
?如果您实际上是实施 forEach
的人,那么您真的不希望那样 - 让 any
浮动是一件危险的事情,很容易打败类型检查.
Why not just use any
? If you're actually the one implementing forEach
, you really don't want that - having an any
floating is a dangerous thing that can defeat typechecking very easily.
由此得出的推论是,如果您有一些返回类型为 void
的函数表达式,您无法确定调用该函数的结果是 undefined
.
The corollary to this is that if you have some function expression whose return type is void
, you cannot say with any certainty that the result of invoking that function is undefined
.
在返回类型明确列为 void
的函数 body 中,TypeScript 将阻止您意外"返回一个值,即使这不会造成类型系统违规.这有助于捕获重构中出现的错误:
In a function body whose return type is explicitly listed as void
, TypeScript will stop you from "accidently" returning a value, even though this wouldn't create a type system violation. This is helpful for catching bugs that appear from a refactoring:
// Old version
function fn(arr: number[]): void {
const arr1 = arr.map(x => {
return 3;
});
}
// New version
function fn(arr: number[]): void {
for (const x of arr) {
// Oops, meant to do something else
return 3;
};
}
这篇关于为什么 TypeScript 有 `void` 和 `undefined`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!