验证函数返回值是否符合函数签名中的条件类型
铁路导向编程either函数的TS类型问题解答
1. 消除编译错误的方法不止类型断言
类型断言是最直接的方案,但还有更优雅的替代方式:
- 使用函数重载:通过定义明确的重载签名,让TS直接关联输入类型和返回类型,无需依赖条件类型的延迟解析。示例代码:
这种写法下TS能精准匹配输入输出类型,不会出现编译错误,同时保留了原函数的功能。type Success<T> = { success: true; result: T }; type Failure<E> = { success: false; cause: E }; // 定义重载签名,明确不同输入对应的返回值 export function either<T, E, U, F>(onSuccess: (i: T) => U, onFailure: (i: E) => F, input: Success<T>): U; export function either<T, E, U, F>(onSuccess: (i: T) => U, onFailure: (i: E) => F, input: Failure<E>): F; // 函数实现 export function either<T, E, U, F>( onSuccess: (i: T) => U, onFailure: (i: E) => F, input: Success<T> | Failure<E> ): U | F { if (input.success) { return onSuccess(input.result); } else { return onFailure(input.cause); } } - 分支内使用类型断言:这就是你提到的方案,在每个return语句后加上针对性的断言,比如
return onSuccess(input.result) as I extends Success<T> ? U : never,但这种写法会让代码略显冗余。
2. TS无法推断返回值匹配条件类型的原因
核心问题是泛型条件类型的延迟解析机制。你的返回类型是一个依赖泛型参数I的条件类型,TS在函数内部做类型检查时,没办法提前确定I具体是Success<T>还是Failure<E>——哪怕你通过input.success做了运行时的类型收窄,TS的类型系统也没法把这个运行时的分支信息和泛型条件类型的解析关联起来。
换句话说:函数内部的类型收窄只能确定当前分支里input的类型,但无法让TS回溯到泛型参数I的约束,也就没法证明当前返回的U或F正好符合条件类型的结果。TS需要明确的类型匹配关系,而泛型条件类型在函数内部属于“未完全解析的类型”,所以会抛出类型不兼容的错误。
内容的提问来源于stack exchange,提问作者Kartik
相关产品推荐
相关产品推荐

