TypeScript父子类方法类型问题:自制迷你ORM编译报错求助
解决迷你ORM的TypeScript类型问题
核心问题分析
你遇到的类型错误根源在于实例方法create的this类型绑定错误,以及静态属性_pk的类型未与实例键名关联:
- 错误地将实例方法
create的this约束为构造函数类型(typeof BaseModel),导致实例调用时类型不匹配(TS2684)。 create方法中误将this当作构造函数,调用实例方法_getParams时触发类型错误(TS2339)。- 静态属性
_pk的类型为string,无法匹配Criteria要求的实例键名类型(TS2322)。
解决方案代码
修改BaseModel类
import { db } from '../db/db'; export interface Criteria<T> { field: Extract<keyof T, string>; value: T[Extract<keyof T, string>]; comparison?: string; } // 泛型K指定主键键名,T指定实例类型 export class BaseModel<K extends string = 'id', T extends BaseModel<K> = BaseModel<K>> { static _pk: string = 'id'; static _table: string = null; constructor(params: Partial<T>) { for (const key in params) { if (Object.prototype.hasOwnProperty.call(params, key)) { const fn = `${key}Process`; if (typeof this[fn] === 'function') { // @ts-ignore 可后续通过类型守卫优化 this[fn](params[key]); } else { // @ts-ignore this[key] = params[key]; } } } } // 实例方法:this指向当前实例 create(): Promise<T> { const params = this._getParams(); // 获取实例对应的构造函数,并约束其类型 const Constructor = this.constructor as typeof BaseModel & { _table: string; _pk: K; findOne: (criteria: Criteria<T>[]) => Promise<T>; }; return db .insertFromModel(Constructor._table, params) .then((id) => Constructor.findOne([{ field: Constructor._pk as Extract<keyof T, string>, value: id as T[Extract<keyof T, string>] }])); } static findOne<T extends typeof BaseModel>(this: T, criteria: Criteria<InstanceType<T>>[]): Promise<InstanceType<T>> { return db.selectFromModel(this._table, criteria, true).then((row: object) => { return new this(row) as InstanceType<T>; }); } _getParams(): Partial<T> { const params: Partial<T> = {}; for (const key of Object.keys(this)) { if (['id', '_table', '_pk'].includes(key)) continue; // @ts-ignore params[key as keyof T] = this[key]; } return params; } }
修改User子类
import { BaseModel } from './BaseModel'; // 指定主键键名为'id',实例类型为User export class User extends BaseModel<'id', User> { static _table = 'users'; static _pk = 'id'; id: number; email: string; password: string; constructor(props: { id?: number; email: string; password: string }) { super(props); } }
关键修改说明
修正
create方法的this类型:
将create的this从构造函数类型改为实例本身,确保new User().create()调用时,this指向User实例,解决TS2684错误。关联主键与实例键类型:
通过泛型K指定主键键名,将Constructor._pk断言为Extract<keyof T, string>,使其符合Criteria的字段类型要求,解决TS2322错误。类型安全优化:
将构造函数参数改为Partial<T>、_getParams返回Partial<T>,让IDE能正确提示实例属性,提升类型安全性。
测试验证
调用代码现在可以正常编译并获得类型提示:
new User({ email: 'test@test.com', password: '123123' }).create().then((user) => { console.log(user.id); // 类型自动推导为number console.log(user.email); // 类型自动推导为string });
内容的提问来源于stack exchange,提问作者kRicha
相关产品推荐
相关产品推荐

