Never 是 Swift 中一个非常特殊的存在,它被称为 "Bottom Type"(底类型) 。它的定义非常简单,但也非常霸道:它是一个没有成员的枚举(Empty Enum) 。
这意味着你永远无法实例化一个 Never 类型的值。正是这种“无法存在”的特性,让它在控制流和泛型中发挥了巨大的逻辑作用。
1. 在控制流中的作用:告知编译器“此路不通”
在 Never 出现之前,执行必死无疑的操作(如 fatalError)返回的是 Void。但 Void 实际上是有值的(即 ()),这会让编译器认为函数执行完后还会继续往下走。
而返回 Never 的函数被称为 Non-returning Function(永不返回的函数) 。
优化逻辑分支
如果你在 guard 语句或 switch 中调用了一个返回 Never 的函数,编译器知道程序在此处会终止,因此不需要你在后面写 return 或 break。
Swift
func crashAndBurn() -> Never {
fatalError("程序在此处终结")
}
func test(input: Int?) {
guard let value = input else {
crashAndBurn() // 编译器知道这里不会返回,所以不需要 return
}
print(value) // 只有成功时才会执行
}
2. 在泛型中的作用:表示“不可能发生的情况”
这是 Never 最精妙的用法。它常被用作泛型占位符,用来在类型层面上关闭某种可能性。
A. Result<Success, Failure>
如果你有一个异步任务,逻辑上它永远不会失败(比如从内存读取配置),你可以这样定义:
Swift
let successOnly: Result<String, Never> = .success("Everything is fine")
因为 Failure 类型是 Never,而 Never 无法产生实例,所以你永远无法构造出一个 .failure 情况。这让处理结果时非常清爽:
Swift
switch successOnly {
case .success(let message):
print(message)
// 不需要写 case .failure,编译器知道它根本不存在
}
B. Combine 中的 Publisher
在 Combine 框架中,如果一个发布者永远不会抛出错误,它的 Failure 类型就会被设为 Never。这允许你使用 .assign(to:on:) 等要求不报错的操作符。
3. 本质:为什么它是 Empty Enum?
在 Swift 中,Never 的底层实现就是一个不带任何 case 的枚举:
Swift
public enum Never {}
根据 Swift 的规则:
- 枚举是值类型。
- 一个没有 case 的枚举无法被初始化。
- 因此,任何声明为
Never的变量都无法被赋予真实的值。
这在类型论中非常完美:Any 是类型的顶峰(包含所有),Never 是底端(不包含任何)。
4. 总结对比
| 场景 | 使用 Never 的效果 |
|---|---|
| 函数返回 | 告知编译器该点之后的代码不可达(Unreachable),消除多余的 return。 |
| 泛型约束 | 逻辑上消除某种状态(如“绝不报错”或“没有数据”)。 |
| 协议实现 | 如果某个协议要求一个关联类型,而你当前的实现不需要它,可以用 Never 填充。 |