TypeScript never类型详解:定义、场景与类型运算特性
本文详细解析TypeScript中never类型的定义、出现场景及核心特性。涵盖函数抛出异常、无限循环及类型缩小中的never表现,并深入探讨其在联合类型过滤、交叉类型运算及赋值规则中的应用,帮助开发者掌握类型系统的深层逻辑。
1. never 类型的理解
在 TypeScript 中,never 类型代表那些永远不会发生的值的类型。
从语义上讲,它表示一种不可能存在的状态,即没有任何值能够属于该类型。
2. 可能会出现 never 类型的一些情况
2.1. 函数抛出异常
当函数执行过程中抛出异常时,其返回类型被推断为 never。这是因为异常抛出会导致程序流立即中断,函数后续的代码(包括返回语句)将无法执行。

在上述示例中,函数 throwError 通过抛出异常来终止执行,将鼠标悬停在函数名上可查看其返回类型被标记为 never。
2.2. 不会有返回值的函数
若函数包含无法结束的无限循环,或始终抛出异常,则该函数的执行永远不会正常结束,因此其返回值类型也被推断为 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; // never3.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 = n3.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 类型的核心概念,更多相关内容可查阅本站往期文章或继续浏览后续教程,感谢支持!
JavaScript闭包与类(Class)的区别及适用场景对比
2026-11-05 15:48:57
JavaScript入门要学ES6吗?let与箭头函数等新特性解析
2026-11-05 14:49:16
JavaScript 8种数据类型详解:基本类型与引用类型的区别
2026-11-05 14:25:15
怎么在JavaScript中使用async/await优化Ajax异步流程
2026-11-05 13:56:15
JavaScript replace回调函数实现动态正则替换逻辑
2026-11-05 13:52:13








