TypeScript泛型类能否继承泛型参数类?Mongoose场景咨询
我正在开发一个后端项目,多个实体共享id和description两个属性,因此定义了包含这些属性的基类BaseEntity:
class BaseEntity { id: string | number; description: string; }
我使用MongoDB数据库和Mongoose ORM,需要为模型和文档定义类型/接口。每个实体类型对应一个文档类型,需包含对应实体的所有属性。一种方式是为每个实体手动定义文档类型,另一种思路是定义泛型DocumentType类,接收实体类型作为参数并继承其所有属性,即:
class DocumentType<ENTITY_TYPE extends BaseEntity> extends ENTITY_TYPE { // 额外属性 }
假设有两个实体类型User和Country:
class User extends BaseEntity { name: string; address: string; phoneNumber: number; }
以及:
class Country { population: string; code: string; }
我期望DocumentType<User>拥有id, description, name, address, phoneNumber属性,DocumentType<Country>拥有id, description, population, code属性。这种实现是否可行?还是只能使用mixin?补充:此前通过//@ts-ignore抑制警告可以运行,但现在完全无法工作。
1. 泛型类继承实体类型的不可行性
你想直接用泛型类继承ENTITY_TYPE的写法在TypeScript里根本行不通——TypeScript不允许类继承一个泛型类型参数。类的继承必须指向具体类,不能是类型参数,这也是你之前靠//@ts-ignore能临时跑通、现在彻底失效的核心原因。
2. 更合适的实现方式
完全不需要用mixin,用接口+交叉类型就能完美解决需求,这也是Mongoose场景下定义文档类型的常规操作:
方式一:自定义基础文档属性+交叉类型
先定义包含通用属性的接口,再和实体类型做交叉合并:
// 基础文档通用属性,后续有额外公共属性可以直接加在这里 interface BaseDocument { id: string | number; description: string; } // 泛型工具类型,生成对应实体的文档类型 type DocumentType<T> = T & BaseDocument; // 使用示例 type UserDocument = DocumentType<User>; // UserDocument 自动包含 id, description, name, address, phoneNumber type CountryDocument = DocumentType<Country>; // CountryDocument 自动包含 id, description, population, code
方式二:结合Mongoose内置类型
如果要保留Mongoose文档的内置方法(比如save()、delete()),可以直接和Mongoose提供的Document类型交叉:
import { Document } from 'mongoose'; type DocumentType<T> = T & BaseEntity & Document; type UserDocument = DocumentType<User>; type CountryDocument = DocumentType<Country>;
3. 为什么不用类?
你需要的本质是类型层面的属性合并,类是运行时存在的结构,用类型别名+交叉类型足够轻量,也完全契合TypeScript的类型系统设计。只有当你需要运行时的类实例结构时,才需要考虑mixin,但对于Mongoose的文档类型定义来说,类型层面的处理就足够了。
内容的提问来源于stack exchange,提问作者Lord Beerus

