TypeScript中如何在子类推断已解析泛型Result的具体类型
实现方案
这个需求完全可以实现,你之前的代码存在几个核心问题导致类型推断失效,逐一修正即可。
原有代码问题梳理
Success类的isError类型守卫逻辑写反了,错误返回true会导致类型收窄完全失效- 抽象工厂的泛型没有加约束,TS无法识别传入参数是
Result类型,自然读不到isError()、value()方法 - 之前写的
typeof Failure/typeof Success是获取类的构造函数类型,不是类实例类型,和实际传入的参数类型不匹配 - 子类中写两个同名
parseSuccess方法不符合TS语法规则,类不支持同名方法的多实现,错误、成功分支需要拆分为两个独立方法处理
修正后的完整实现
1. 先修复基础Result类的类型守卫bug
export type Result<E, S> = Failure<E, S> | Success<E, S>; export class Failure<E, S> { constructor(private _value: E) {} isError(): this is Failure<E, S> { return true; } value(): E { return this._value } isSuccess(): this is Success<E, S> { return false; } } export class Success<E, S> { constructor(private _value: S) {} value(): S { return this._value; } // 修复:错误场景才返回true,成功场景isError必须返回false isError(): this is Failure<E, S> { return false; } isSuccess(): this is Success<E, S> { return true; } }
2. 改造通用HTTP响应抽象工厂
通过infer条件类型从传入的Result泛型中自动提取错误值、成功值类型,同时给泛型加约束确保类型合法:
// 工具类型:从Result中提取错误值类型 type ExtractErrorType<T> = T extends Result<infer E, any> ? E : never; // 工具类型:从Result中提取成功值类型 type ExtractSuccessType<T> = T extends Result<any, infer S> ? S : never; abstract class HttpResponseFactory<T extends Result<any, any>> { public make(result: T): HttpResponse { if (result.isError()) { // 类型自动收窄为错误分支,value()返回类型自动推断为对应错误类型 return this.parseError(result.value()); } // 类型自动收窄为成功分支,value()返回类型自动推断为对应成功类型 return this.parseSuccess(result.value()); } // 默认错误处理返回500,子类可重写自定义不同错误的状态码、返回结构 protected parseError(error: ExtractErrorType<T>): HttpResponse { return response.status(HttpCode.InternalServerError).json({}) } // 要求子类必须实现成功场景的响应逻辑 protected abstract parseSuccess(result: ExtractSuccessType<T>): HttpResponse; }
3. 子类实现示例
子类只需要传入对应的Result类型作为泛型参数,TS会自动推断parseError、parseSuccess的参数类型,不需要手动声明:
// 原有业务类型定义 class UserAlreadyExistsError extends Error {} class UnexpectedError extends Error {} class User { constructor(private name: string) {} } type CreateUserResult = Result<UserAlreadyExistsError | UnexpectedError, User>; class CreateUserHttpResponseFactory extends HttpResponseFactory<CreateUserResult> { // 参数自动推断为User类型 protected parseSuccess(user: User): HttpResponse { return response.status(HttpCode.Created).json({ code: HttpCode.Created, data: user, message: "用户创建成功" }) } // 参数自动推断为UserAlreadyExistsError | UnexpectedError类型 protected override parseError(error: UserAlreadyExistsError | UnexpectedError): HttpResponse { if (error instanceof UserAlreadyExistsError) { return response.status(HttpCode.Conflict).json({ code: HttpCode.Conflict, message: "用户已存在" }) } // 其余错误走默认500逻辑 return super.parseError(error); } }
使用效果
控制器层注入工厂后调用完全符合类型校验,不需要额外的类型断言:
class CreateUserController { constructor(private createUserHttpResponseFactory: CreateUserHttpResponseFactory) {} create(request: HttpRequest): HttpResponse { const createUserResult = new CreateUserUseCase().execute({}); // 入参自动校验为CreateUserResult类型,返回值自动识别为HttpResponse return this.createUserHttpResponseFactory.make(createUserResult); } }
内容的提问来源于stack exchange,提问作者Thiago Dias
相关产品推荐
相关产品推荐

