0%

TS中never类型有什么作用?

bottom type

首先, never是一个bottom type,这如何体现呢?

image.png
:✅表示 strictNullChecksfalse时的情况

neverunknown朝着两个相反的方向行进,所有的类型都可以赋值给unknown, never可以赋值给任何类型;unknown不能赋值给除any和自身之外的任何类型,除never本身外,任何类型都不能赋值给never

应用场景

  1. 用于从来不会返回值的函数

    这可能有两种情况,一是函数中可能死循环

    1
    2
    3
    4
    5
    function loop():never {
    while(true) {
    console.log('I always does something and never ends.')
    }
    }

    另外一种情况就是这个函数总是会抛出一个错误,因此也总是没有返回值

    1
    2
    3
    function loop():never {
    throw new Error('error!')
    }
  2. 穷尽检查(Exhaustiveness checking)

    对于一个联合类型,将其类型收窄为never

    1
    2
    3
    4
    5
    6
    7
    interface Foo {
    type: 'foo'
    }
    interface Bar {
    type: 'bar'
    }
    type All = Foo | Bar
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function handleValue(val: All) {
    switch (val.type) {
    case 'foo':
    // 这里 val 被收窄为 Foo
    break
    case 'bar':
    // val 在这里是 Bar
    break
    default:
    // val 在这里是 never
    const exhaustiveCheck: never = val
    break
    }
    }

    通过case 对可能的类型进行了相应处理,因此defaultval的类型是never,这也体现了never是一个底层类型:never只能赋值给never。如果之后联合类型All中添加了新的类型,但是在代码中忘记进行相应处理,那么就能提前暴露处错误,提醒开发者进行处理。

    never和void的区别

    1. 从赋值的角度来看,undefined可以赋值给void类型的变量,除了never本身,任何值都不能赋值给never类型,也就是说never意味着没有任何值。

      注:strictNullChecksfalse时,null类型也是可以赋值给void

    2. void 表示一个函数并不会返回任何值,当函数并没有任何返回值,或者返回不了明确的值的时候,就应该用这种类型。

      never表示一个函数从来不返回值,可能这个函数处于死循环,一直在运行,也可能这个函数运行过程中报错;never只能赋值给never,可以利用这个特性进行穷尽检查(Exhaustiveness checking)

注:

当基于上下文的推导,返回类型为void时,不会强制返回函数一定不能返回内容,也就是说当这样一个类型(type vf = () => void)被应用时,也是可以返回值的,只不过返回的值会被忽略。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
type voidFunc = () => void;

const f1: voidFunc = () => {
return true;
};

let a = f1() //let a: void

const f2: voidFunc = () => true;

let b = f2() //let b: void
const f3: voidFunc = function () {
return true;
};

let c = f3() //let c: void

可以看到a b c的类型都是void

但当一个函数字面量定义返回一个 void 类型,函数是一定不能返回任何东西的

1
2
3
4
5
6
7
function f2(): void {
return true; //Type 'true' is not assignable to type 'void'.
}

const f3 = function (): void {
return true; //Type 'true' is not assignable to type 'void'.
};

参考

ts handbook

strictNullChecks