优化TypeScript的Result条件类型时,fail函数出现类型不兼容错误
优化TypeScript的Result条件类型时,fail函数出现类型不兼容错误
我来帮你拆解这个问题的根源,以及对应的解决方案:
首先,咱们先看报错的原因:你的fail函数返回类型是Result<never, E>,用你原来的条件类型定义,当E不是never时,这个Result<never, E>会被解析成Success<never> | Failure<E>。虽然Success<never>在实际运行中根本没法构造(因为value是never类型,没有任何值能匹配),但TypeScript的类型检查器会严格遵循你定义的类型规则,认为你返回的Failure<E>没有覆盖Success<never>这个分支,所以抛出了类型不兼容的错误。
而你的succeed函数之所以没问题,是因为它返回的是Result<T, never>,刚好匹配到条件类型里的第一个分支,直接返回Success<T>,和函数返回值完全对应,所以类型校验能通过。
解决方案:调整Result的条件类型,同时处理T为never的场景
我们可以给Result的条件类型再加一个分支,专门处理T为never的情况,这样fail函数的返回类型就能准确匹配Failure<E>了:
type Success<T> = { success: true, value: T } type Failure<E> = { success: false, error: E } type Result<T, E = never> = // 当E是never时,只返回Success<T>(对应succeed的场景) [E] extends [never] ? Success<T> : // 当T是never时,只返回Failure<E>(对应fail的场景) [T] extends [never] ? Failure<E> : // 其他情况返回成功/失败的联合类型 Success<T> | Failure<E> function succeed<T>(value: T): Result<T, never> { return { success: true, value } } function fail<E>(error: E): Result<never, E> { return { success: false, error } // 现在类型校验完全通过 } function test(value: string): Result<string, string> { if (!value) { // 原代码里value是string类型,不会是undefined,这里调整成更合理的空值判断 return fail("empty"); } else { return succeed(value); } }
额外说明
这里用[E] extends [never]而不是直接E extends never,是为了避免条件类型的分配性问题。如果E是联合类型的话,直接E extends never会把联合类型拆开来逐个判断,而用元组包裹后,会把整个E作为一个整体来判断,这是TypeScript里处理条件类型的常用小技巧。
备注:内容来源于stack exchange,提问作者Faz
相关产品推荐
相关产品推荐

