如何通过类属性自动推导泛型,简化Express自定义Controller的继承写法
这种实现方式完全可行,我们可以通过给基类泛型设置默认值,配合TypeScript的实例类型推断能力实现你要的效果,不需要每次继承时手动传入泛型参数。
具体实现方案
1. 修改Controller基类
给泛型参数设置默认值,同时放宽querySchema的初始类型限制,让子类可以自行收窄类型:
import { Request, Response } from 'express'; import { transvalidate } from './schema/transform-validate'; import { ClassConstructor } from 'class-transformer'; // 给泛型加默认值,子类继承时可省略传参 export abstract class Controller<QuerySchema extends object = object> { querySchema?: ClassConstructor<any>; query?: QuerySchema; constructor( protected readonly req: Request, protected readonly res: Response, ) { if (this.querySchema) { this.query = transvalidate(this.querySchema, this.req.query); } } getQuery(): QuerySchema { if (!this.query) { throw new Error( `Can't get query. Probably the querySchema is not provided.`, ); } return this.query; } abstract handle(): Promise<unknown>; }
2. 子类写法
直接按你期望的方式编写即可,不需要额外传入泛型参数:
import { Controller } from './controller'; import { GetCatsQuerySchema } from './schema/query.schema'; // 无需手动传入泛型参数 export class CatsController extends Controller { querySchema = GetCatsQuerySchema; handle(): Promise<unknown> { // this.getQuery() 仍然会返回准确的 GetCatsQuerySchema 类型,类型提示完全正常 const query = this.getQuery(); return Promise.resolve(undefined); } }
注意事项
- 要求TypeScript版本 ≥ 4.4,才能支持完整的子类属性反向类型推断
- 现有代码中的
GetCatsQuerySchema存在类型不匹配问题:age字段通过@Type(() => Number)转为数字类型,同时用@IsInt()做整数校验,但类型声明为string,建议修改为age?: number - 该实现不会损失任何类型安全性,所有类型校验和提示逻辑和原有写法完全一致
内容的提问来源于stack exchange,提问作者Farad
相关产品推荐
相关产品推荐

