如何在非静态类属性对象中正确使用this类型参数?
TypeScript中this类型在类成员中的正确使用问题
问题现象
- 抽象类
BaseModel中,使用this作为类型的属性attributes报错,错误提示:
A 'this' type is available only in a non-static member of a class or interface.
- 继承
BaseModel并重写attributes后,回调函数的row参数类型未正确推断为子类fields对应的类型,而是显示为any。
错误代码示例
抽象类定义:
export abstract class BaseModel { // 报错的属性 attributes?: { [key: string]: <T extends FieldsResult<this>>(row: T) => any }; // 正常工作的方法 where<K extends keyof Fields<this>>(field: K, key: '_is_null', value: boolean): this; }
子类继承后的问题:
export class UsersModel extends BaseModel { override fields = { first: '', last: '' } override attributes = { // row应推断为{first: string, last: string},实际为any full: row => `${row.last}, ${row.first}`, } }
问题原因
- 属性报错原因:在对象字面量的泛型函数内部使用
this类型是TypeScript不允许的行为,而类方法的泛型参数可以正常使用this类型,这是两者的语法差异。 - 类型推断失效原因:原定义中
attributes的泛型约束没有正确绑定到当前类的this上下文,导致子类继承时无法传递fields的类型信息。
解决方案
方案一:移除函数内部泛型,直接绑定this类型
修改BaseModel中attributes的类型定义,去掉函数内部的泛型声明,直接将row参数类型指定为FieldsResult<this>:
export abstract class BaseModel { // 修正后的属性类型 attributes?: { [key: string]: (row: FieldsResult<this>) => any }; where<K extends keyof Fields<this>>(field: K, key: '_is_null', value: boolean): this; }
此时子类UsersModel中的row参数会自动推断为{first: string, last: string},无需额外注解。
方案二:使用泛型类绑定fields类型
将BaseModel改为泛型类,显式绑定fields的类型,让类型推断更清晰:
// 定义泛型抽象类 export abstract class BaseModel<F extends Record<string, any>> { abstract fields: F; attributes?: { [key: string]: (row: F) => any }; where<K extends keyof F>(field: K, key: '_is_null', value: boolean): this; } // 子类继承时指定泛型类型 export class UsersModel extends BaseModel<{ first: string; last: string }> { override fields = { first: '', last: '' }; override attributes = { full: (row) => `${row.last}, ${row.first}`, // row类型正确推断 }; }
这种方式更直观,适合需要严格约束fields结构的场景。
内容的提问来源于stack exchange,提问作者Get Off My Lawn
相关产品推荐
相关产品推荐

