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

TypeScript中如何在函数内实例化抽象类的子类类型?

Node.js TypeScript 请求验证器实现方案

问题描述

我正在开发一个Node.js TypeScript项目,定义了抽象类RequestValidator作为验证器契约,子类需实现getSchema方法提供Joi验证规则:

import { Request, Response } from 'express';
import joi from 'joi';

export abstract class RequestValidator {
  abstract getSchema(req: Request, res?: Response): joi.ObjectSchema;
}

class LoginFormValidator extends RequestValidator {
  getSchema(req: Request, res?: Response): joi.ObjectSchema {
    return {
       email: joi.string().required(),
       password: joi.string().required()
    } as joi.ObjectSchema; // 示例代码,实际应返回joi.object()
  }
}

核心需求:

  • 客户端仅需传入验证器类,无需手动创建实例
  • validateRequest函数内部负责实例化验证器类
  • 客户端必须遵循RequestValidator的契约

正确实现方式

直接使用typeof RequestValidator会因为抽象类无法实例化报错,需要定义构造函数类型来约束传入的类必须是可实例化的RequestValidator子类:

// 定义构造函数类型:能实例化出RequestValidator的类
type ValidatorConstructor = new () => RequestValidator;

const validateRequest = (validatorClass: ValidatorConstructor) => {
  // 内部创建验证器实例
  const validator = new validatorClass();
  
  // 示例:结合Request获取验证规则并执行验证
  const mockReq = {} as Request; // 实际业务中使用真实req对象
  const schema = validator.getSchema(mockReq);
  const validationResult = schema.validate(mockReq.body);
  
  if (validationResult.error) {
    // 处理验证失败逻辑,比如返回错误响应
    console.error(validationResult.error.details);
  }
  
  return validationResult;
};

// 调用方式
validateRequest(LoginFormValidator);

关键说明

  • ValidatorConstructor类型确保传入的类必须能无参实例化出RequestValidator实例
  • 如果子类需要构造函数参数,可以调整构造签名,比如new (someParam: Type) => RequestValidator
  • 修正LoginFormValidator的getSchema实现:直接返回joi.object()而非类型断言,避免类型不安全:
    class LoginFormValidator extends RequestValidator {
      getSchema(req: Request, res?: Response): joi.ObjectSchema {
        return joi.object({
          email: joi.string().required(),
          password: joi.string().required()
        });
      }
    }
    

替代方案:静态方法实现

如果验证器不需要维护实例状态,可以将getSchema改为静态方法,无需实例化即可调用:

export abstract class RequestValidator {
  static abstract getSchema(req: Request, res?: Response): joi.ObjectSchema;
}

class LoginFormValidator extends RequestValidator {
  static getSchema(req: Request, res?: Response): joi.ObjectSchema {
    return joi.object({
      email: joi.string().required(),
      password: joi.string().required()
    });
  }
}

const validateRequest = (validatorClass: typeof RequestValidator) => {
  const mockReq = {} as Request;
  const schema = validatorClass.getSchema(mockReq);
  const validationResult = schema.validate(mockReq.body);
  
  // 处理验证逻辑...
  return validationResult;
};

// 调用方式不变
validateRequest(LoginFormValidator);

这种方案更简洁,避免了实例化的开销,适合无状态的验证场景。

内容的提问来源于stack exchange,提问作者Wai Yan Hein

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:22:38