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
相关产品推荐
相关产品推荐

