void和never都是函数返回类型的一种,但是它们有很大的区别。void表示函数不返回任何值,而never表示函数永远不会返回。在实际编程中,void通常用于表示函数执行了某些操作但不需要返回值,而never通常用于表示函数会抛出异常或陷入无限循环等情况,从而永远不会返回。
void
表示函数执行了某些操作但不需要返回值。举个例子:
function f1() {
console.log(123)
}
function f2() {
return
}
// 这两种情况下函数的类型为void,比较容易理解
never
表示函数会抛出异常或陷入无限循环等情况,从而永远不会返回,而且never
类型的参数只能接受never
类型的对象。
举个例子:
// 抛出异常
function f3(): never {
throw new Error('抛出异常')
}
// 无限循环
function f4(): never {
while(true) {}
}
乍一看,好像没啥用,再仔细一看,好像确实没啥用。
不过对于never
也有对应的使用场景,可以验证逻辑判断是否准确。举例如下:
function f5(val: number | string) {
switch (typeof val) {
case 'number':
// 类型为number进行的处理
break;
case 'string':
// 类型为string进行的处理
break;
default:
break;
}
}
函数f5
中,根据参数val
不同的类型分别进行不同的操作,这里没有什么问题。
但是如果参数val
再加一个object
类型,这个时候如果下面switch
中忘记写对应的处理,代码层次上是没有问题的,但是逻辑上是不符合我们要求的,如下:
// 参数有object类型,但是未对object进行单独处理,代码也不会报错
function f5(val: number | string | object) {
switch (typeof val) {
case 'number':
// 类型为number进行的处理
break;
case 'string':
// 类型为string进行的处理
break;
default:
break;
}
}
所以,此时就可以借助never
进行判断,在default
块中加上一个never
类型的参数并赋值为val
,由于任何类型的值都不能赋值给never
类型的参数,所以此处到default
时的类型为object
,就会报错。
function f5(val: number | string | object) {
switch (typeof val) {
case 'number':
// 类型为number进行的处理
break;
case 'string':
// 类型为string进行的处理
break;
default:
const check: never = val
break;
}
}
想要避免错误,只需要把object
的判断加上,而且如果逻辑完全正确也不会走到default
function f5(val: number | string | object) {
switch (typeof val) {
case 'number':
// 类型为number进行的处理
break;
case 'string':
// 类型为string进行的处理
break;
case 'object':
// 类型为object进行的处理
break;
default:
const check: never = val
break;
}
}