TypeScript中如何让包装函数Options内的valid函数this类型正确推断?
问题:让包装函数中options的valid方法this类型正确推断
我想要实现一个类似Vue组件的包装函数,接收包含fields、valid等属性的options对象,返回对应的model对象。核心需求是:options里的valid方法通过this访问最终model的所有属性时,能获得正确的类型提示和自动补全。
当前代码存在的问题是,valid方法内的this被推断为泛化的Model<Opts>,无法识别具体的属性(比如this.x、this.child.p):
type Opts = { fields: { [k: string]: { label: string } | Opts } valid?: (this: Model<Opts>) => boolean } type Model<T extends Opts> = { [P in keyof T['fields']]: T['fields'][P] extends Opts ? Model<T['fields'][P]> : number } & { readonly $meta: { /* some additional model details */ } } function wrap<T extends Opts>(opts: T): Model<T> { // some wrapper implementation I don't care about here } const sample = wrap({ fields: { x: { label: 'X' }, y: { label: 'Y' }, child: { fields: { p: { label: 'P' }, q: { label: 'Q' }, }, }, }, valid() { // this 类型是 Model<Opts>,无法识别 x、child.p 等具体属性 return this.x > 0 && this.child.p > 0 }, })
解决方案
要解决这个问题,需要让Opts的泛型参数和Model的类型建立直接关联,让TypeScript能根据传入的具体options推断出this的准确类型。修改后的代码如下:
// 让 Opts 接收一个泛型参数,代表当前配置对应的 Model 类型 type Opts<M> = { fields: { [k: string]: { label: string } | Opts<any> } valid?: (this: M) => boolean } // Model 类型保持原有逻辑,但需要和 Opts 关联 type Model<T extends Opts<any>> = { [P in keyof T['fields']]: T['fields'][P] extends Opts<infer M> ? M : number } & { readonly $meta: { /* some additional model details */ } } // 定义一个辅助类型,用于将 Opts 和对应的 Model 绑定 type OptsWithModel<T> = Opts<Model<OptsWithModel<T>>> & { fields: T } // 重新定义 wrap 函数,利用辅助类型推断准确的 this 类型 function wrap<T>(opts: OptsWithModel<T>): Model<typeof opts> { // some wrapper implementation I don't care about here return {} as Model<typeof opts> } const sample = wrap({ fields: { x: { label: 'X' }, y: { label: 'Y' }, child: { fields: { p: { label: 'P' }, q: { label: 'Q' }, }, }, }, valid() { // 现在 this 能正确识别 x、y、child 等属性,支持自动补全和类型检查 return this.x > 0 && this.child.p > 0 }, })
关键修改点
- 将
Opts改为接收泛型参数M,明确valid方法的this指向对应的Model类型; - 新增
OptsWithModel辅助类型,递归绑定Opts和其对应的Model,让TypeScript能递归推断嵌套结构的类型; - 调整
wrap函数的泛型定义,利用typeof opts让TypeScript根据传入的具体配置推断出完整的Model类型,从而让valid方法的this获得准确的类型提示。
内容的提问来源于stack exchange,提问作者repka
相关产品推荐
相关产品推荐

