TypeScript never类型详解:定义、场景与类型运算特性

作者:半夏时间:2026-10-31 07:07:40浏览:642

本文详细解析TypeScript中never类型的定义、出现场景及核心特性。涵盖函数抛出异常、无限循环及类型缩小中的never表现,并深入探讨其在联合类型过滤、交叉类型运算及赋值规则中的应用,帮助开发者掌握类型系统的深层逻辑。

1. never 类型的理解

在 TypeScript 中,never 类型代表那些永远不会发生的值的类型。

从语义上讲,它表示一种不可能存在的状态,即没有任何值能够属于该类型。

2. 可能会出现 never 类型的一些情况

2.1. 函数抛出异常

当函数执行过程中抛出异常时,其返回类型被推断为 never。这是因为异常抛出会导致程序流立即中断,函数后续的代码(包括返回语句)将无法执行。

1. never 类型的理解

在上述示例中,函数 throwError 通过抛出异常来终止执行,将鼠标悬停在函数名上可查看其返回类型被标记为 never。

2.2. 不会有返回值的函数

若函数包含无法结束的无限循环,或始终抛出异常,则该函数的执行永远不会正常结束,因此其返回值类型也被推断为 never。

1. never 类型的理解

例如 infiniteLoop 函数包含一个没有终止条件的无限循环,程序执行将永远停滞在此,不会到达任何返回语句,故其返回类型为 never。

2.3. 类型判断或类型缩小的细化(全面性检查)

在条件分支中,如果 TypeScript 的类型系统推断出某个分支逻辑上不可能被执行,该分支内的变量类型会被细化为 never。

type Value = number | string;
const processValue = (value: Value) => {
  if (typeof value === "number") {
    // 在这个分支中,value 的类型被细化为 number
  } else if (typeof value === "string") {
    // 在这个分支中,value 的类型被细化为 string
  } else {
    // 在这个分支中,value 的类型被细化为 never,因为 value 不可能同时为 string 和 number
    const n: never = value
  }
}

在示例代码中,else 分支内的 value 变量类型被细化为 never。此时若将 value 赋值给显式声明为 never 类型的变量,代码可正常编译。但若将 value 的初始类型改为 number | string | boolean 的联合类型,else 分支中 value 的类型将细化为 boolean,此时尝试将其赋值给 never 类型变量会引发类型错误。

type Value = number | string | boolean;
const processValue = (value: Value) => {
  if (typeof value === "number") {
    // 在这个分支中,value 的类型被细化为 number
  } else if (typeof value === "string") {
    // 在这个分支中,value 的类型被细化为 string
  } else {
    // 在这个分支中,value 的类型被细化为 boolean 类型,因为 value 不可能同时为 string 和 number
    // 此时,把 value 赋值给一个显示声明了 never 类型的变量 n 就会报错。
    // 下面的赋值语句会报错:不能将类型“boolean”分配给类型“never”。
    const n: never = value
  }
}

3. never 类型的特点

3.1. never 类型会从联合类型中移除

任何类型与 never 进行联合运算,结果均为该类型本身。这类似于数学中任意数加 0 等于其本身的性质。

type T1 = number | never;  // number
type T2 = string | never;  // string
type T3 = boolean | never; // boolean
type T4 = any | never;     // any
type T5 = unknown | never; // unknown
type T6 = never | never;   // never
type T7 = "abc" | never;   // "abc"
type T8 = 123 | never;     // 123

利用这一特性,可以实现类型筛选功能。

通过条件类型将不符合目标 Type 的类型转换为 never,再利用联合类型的自动去重特性过滤掉 never,即可得到期望的类型结果。

type Filter<T, U> = T extends U ? T : never
type RESULT = Filter<"Echo" | 26 | true | "GuangZhou", string>

上述代码遵循分布式条件类型机制,Filter<"Echo" | 26 | true | "GuangZhou", string> 将被分解处理如下:

type RESULT = 
  | ("Echo" extends string ? "Echo" : never) 
  | (26 extends string ? 26 : never) 
  | (true extends string ? true : never) 
  | ("GuangZhou" extends string ? "GuangZhou" : never)

进一步解析后,得到如下中间状态:

type RESULT = "Echo" | never | never | "GuangZhou"

最终解析结果为:

type RESULT = "Echo" | "GuangZhou"

3.2. never 类型与任意类型的交叉类型都是 never

type T1 = number & never;  // never
type T2 = string & never;  // never
type T3 = boolean & never; // never
type T4 = any & never;     // never
type T5 = unknown & never; // never
type T6 = never & never;   // never
type T7 = "abc" & never;   // never
type T8 = 123 & never;     // never

3.3. never 可以赋值给任意类型

由于 never 是所有类型的子类型,因此 never 类型的值可以赋值给任何其他类型。

let n: never
let str: string = n
let num: number = n
let b: boolean = n
let any: any = n
let unknown: unknown = n
let func: () => void = n
let symbol: symbol = n
let n1: never = n

3.4. 其他类型不能赋值给 never

由于 never 没有子类型(除了它自己),因此除了 never 本身,任何其他类型的值都不能赋值给 never 类型的变量。

let n: never
n = "Echo"               // 报错:不能将类型“string”分配给类型“never”
n = 26                   // 报错:不能将类型“number”分配给类型“never”
n = true                 // 报错:不能将类型“boolean”分配给类型“never”
n = [1, 2, 3]            // 报错:不能将类型“number[]”分配给类型“never”
n = Symbol()             // 报错:不能将类型“symbol”分配给类型“never”
n = {}                   // 报错:不能将类型“{}”分配给类型“never”
n = new Array()          // 报错:不能将类型“any[]”分配给类型“never”
n = (...arg: any) => {}  // 报错:不能将类型“(...arg: any) => void”分配给类型“never”

4. 总结

以上是对 TypeScript 中 never 类型的详细解析,如有不当之处,欢迎在评论区指正!

本文介绍了 TypeScript 中 never 类型的核心概念,更多相关内容可查阅本站往期文章或继续浏览后续教程,感谢支持!

作者最新文章
相关文章
更多