You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何递归提取Swift枚举中最深层的关联值?

递归获取最深层嵌套关联值的类型约束解决方案

要解决泛型类型必须显式指定的问题,核心思路是用递归协议+编译期类型推导,让编译器自动识别递归的终止条件,不需要手动指定每一层的类型。

1. 定义递归标记协议

先给CasePathable扩展一个专属协议,用来区分“有嵌套关联值”和“无嵌套关联值”的类型:

import CasePaths

// 标记具备嵌套关联值的类型
protocol NestedCasePathable: CasePathable where AllCasePaths: CasePathReflectable<Self> {
    // 关联类型:当前枚举的关联值类型
    associatedtype NestedValue: CasePathable where NestedValue.AllCasePaths: CasePathReflectable<NestedValue>
}

// 给NestedCasePathable添加默认的关联值提取方法
extension NestedCasePathable {
    func extractNestedValue() -> NestedValue? {
        let caseKeyPath = Self.allCasePaths[self]
        return self[case: caseKeyPath] as? NestedValue
    }
}

2. 让枚举适配协议

针对你的示例枚举,给有嵌套的类型指定关联类型,无嵌套的类型则不遵守NestedCasePathable:

@CasePathable
enum A: NestedCasePathable {
    typealias NestedValue = B
    case a(B)
    case smthA
}

@CasePathable
enum B: NestedCasePathable {
    typealias NestedValue = C
    case b(C)
    case smthB
}

@CasePathable
enum C: CasePathable { // C没有关联值,作为递归终止节点
    case c
    case smthC
}

3. 实现通用递归函数

通过重载泛型函数,利用协议约束自动处理递归逻辑:

// 递归终止:非NestedCasePathable类型直接返回自身
func getDeepestValue<T: CasePathable>(_ value: T) -> T where T.AllCasePaths: CasePathReflectable<T> {
    value
}

// 递归逻辑:NestedCasePathable类型继续提取并递归
func getDeepestValue<T: NestedCasePathable>(_ value: T) -> some CasePathable {
    if let nested = value.extractNestedValue() {
        return getDeepestValue(nested)
    }
    return value
}

实际测试

现在调用时不需要显式指定任何类型,编译器会自动推导到最深层:

let aValue: A = .a(.b(.c))
let deepest = getDeepestValue(aValue) // 自动推导为C类型,值为.c

// 测试中间终止的情况
let aValue2: A = .a(.smthB)
let deepest2 = getDeepestValue(aValue2) // 类型为B,值为.smthB

核心原理

  • 用NestedCasePathable协议标记可递归的类型,通过关联类型明确下一层的类型,让编译器能自动推导递归链路。
  • 利用Swift的不透明类型some CasePathable,隐藏递归过程中的类型细节,同时保证返回值的类型安全。
  • 函数重载自动区分终止条件和递归逻辑,无需手动干预类型判断。

内容的提问来源于stack exchange,提问作者Roman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 07:16:17