使用fp-ts的sequenceS处理不同Left类型Either的类型推断问题
解决fp-ts中sequenceS无法自动推断Left联合类型的问题
当使用fp-ts的sequenceS函数处理多个不同Left类型的Either时,TypeScript无法自动将多个Left类型推断为联合类型,导致出现类型不兼容错误。
示例代码:
import * as E from 'fp-ts/Either' type EmailValidationError = { type: 'EmailError' } type UsernameValidationError = { type: 'UsernameError' } type Email = string declare function validateEmail(email: string): E.Either<EmailValidationError, Email> declare function validateUsername(username: string): E.Either<UsernameValidationError, Email> function validateData(inputs: { email: string; username: string }) { return E.sequenceS(E.Apply)({ email: validateEmail(inputs.email), username: validateUsername(inputs.username), }) }
错误信息:
Type 'UsernameValidationError' is not assignable to type 'EmailValidationError'.
解决方案
1. 封装自动推断联合类型的sequenceS工具函数
封装通用工具函数,自动提取所有Either的Left类型并组成联合类型,无需手动指定:
import * as E from 'fp-ts/Either' // 封装自动推断Left联合类型的sequenceS工具 const sequenceSEither = <T extends Record<string, E.Either<any, any>>>(validations: T) => E.sequenceS(E.Apply)< T[keyof T] extends E.Either<infer L, any> ? L : never >()(validations) as E.Either< T[keyof T] extends E.Either<infer L, any> ? L : never, { [K in keyof T]: T[K] extends E.Either<any, infer R> ? R : never } > // 使用工具函数 function validateData(inputs: { email: string; username: string }) { return sequenceSEither({ email: validateEmail(inputs.email), username: validateUsername(inputs.username), }) }
2. 显式放宽Apply类型约束
通过将E.Apply的类型显式放宽,让TypeScript自动推断联合类型:
function validateData(inputs: { email: string; username: string }) { return E.sequenceS(E.Apply as E.Apply<E.Either<any, any>>)({ email: validateEmail(inputs.email), username: validateUsername(inputs.username), }) }
3. 利用类型推断提取联合类型
先将验证结果存入变量,自动提取Left联合类型后传入sequenceS:
function validateData(inputs: { email: string; username: string }) { const validations = { email: validateEmail(inputs.email), username: validateUsername(inputs.username), } // 自动提取所有Left类型的联合 type LeftErrors = typeof validations[keyof typeof validations] extends E.Either<infer L, any> ? L : never return E.sequenceS(E.Apply)<LeftErrors>(validations) }
内容的提问来源于stack exchange,提问作者David Novák
相关产品推荐
相关产品推荐

