在TypeScript中,您可以将函数注释为返回void
:
function fn1(): void {
// OK
}
function fn2(): void {
// Error
return 3;
}
您还可以注释一个函数以返回undefined
:
function fn3(): undefined {
// OK
return;
}
function fn4(): undefined {
// Error
return 3;
}
因此,如果您调用返回void
的函数,似乎总是会得到值undefined
。但是您不能编写以下代码:
function fn5(): void {
}
let u: undefined = fn5(); // Error
为什么void
不仅仅是undefined
的别名?它根本不需要存在吗?
答案 0 :(得分:5)
void
在函数返回类型中具有特殊含义,不是undefined
的别名。这样想是非常错误的。为什么?
void
的意图是将不会观察到函数的返回值 。这与将是undefined
完全不同。重要的是要有这种区别,以便您可以正确描述诸如forEach
之类的函数。让我们考虑一个Array#forEach
的独立版本,它在回调返回位置用undefined
而不是void
编写:
declare function forEach<T>(arr: T[], callback: (el: T) => undefined): void;
如果您尝试使用此功能:
let target: number[] = [];
forEach([1, 2, 3], el => target.push(el));
您会得到一个错误:
“数字”类型不能分配给“未定义”类型
这是一个正确的错误-您说您想要一个返回值undefined
的函数,但实际上您提供了一个返回值number
的函数,因为这就是Array#push
返回的原因!
使用void
意味着forEach
承诺不使用返回值,因此可以通过返回任何值的回调来调用它
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
是很危险的事情,很容易导致类型检查失败。
这的必然结果是,如果您有某个函数表达式的返回类型为void
,则您不能肯定地说调用该函数的结果为undefined
。
void
不是undefined
的别名,并且类型void
的表达式可能具有 any 值,而不是只是undefined
在函数 body 中,其返回类型显式列出为void
,即使不会造成类型系统冲突,TypeScript也会阻止您“意外”返回值。 。这对于捕获重构中出现的错误很有帮助:
// 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;
};
}
答案 1 :(得分:0)
因此,从这个角度来看,number | void
应该解析为void
对吗?
由于您不应观察到类型void
的值,因此由于void|number
部分的原因,您也无法检查number
是否实际上是void
。任何值。也可能是一个不应该被观察到的数字。