You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript抽象类与接口方法返回自身实现类实例类型的解决方案

解决方案

有两种常用方案可以实现这个需求,优先推荐使用TypeScript内置的多态this类型,实现成本最低也最符合语义。

方案1:使用多态this类型

这个类型会自动指向当前调用方法的实例的实际类型,不需要额外声明泛型,改法非常简单:
首先修改基接口和基类定义:

export interface IPersonViewModel {
    name: string;
    // 把返回值从IPersonViewModel改为this
    setName(value: string): this;
}

export abstract class PersonViewModel implements IPersonViewModel {
    constructor(name: string) {
        this.name = name;
    }

    public name: string;

    public setName(value: string): this {
        // 用类型断言告知TS返回值符合当前实例类型,扩展运算符已拷贝所有实例属性,断言是安全的
        const vm = { ...this, name: value } as this;
        return vm;
    }
}

派生接口和派生类无需做任何修改,此时在IEmployeeViewModel实例上调用setName方法,返回值会自动被推导为IEmployeeViewModel类型,测试效果如下:

const emp = new EmployeeViewModel('engineer', '张三');
const newEmp = emp.setName('李四');
// newEmp类型自动识别为IEmployeeViewModel,可正常调用派生类方法
const newEmp2 = newEmp.setRole('senior engineer'); // 无类型报错

方案2:使用泛型约束

如果你的场景需要更灵活的类型控制,也可以给基接口和基类增加泛型参数:

// 基接口增加泛型参数T,默认约束为IPersonViewModel类型
export interface IPersonViewModel<T extends IPersonViewModel = IPersonViewModel> {
    name: string;
    setName(value: string): T;
}

// 基类同步增加泛型参数
export abstract class PersonViewModel<T extends IPersonViewModel = IPersonViewModel> implements IPersonViewModel<T> {
    constructor(name: string) {
        this.name = name;
    }

    public name: string;

    public setName(value: string): T {
        const vm = { ...this, name: value } as T;
        return vm;
    }
}

派生时将自身类型作为泛型参数传入即可:

// 派生接口传入自身类型作为泛型参数
export interface IEmployeeViewModel extends IPersonViewModel<IEmployeeViewModel> {
    role: string;
    setRole(value: string): IEmployeeViewModel;
}

// 派生类同步传入自身类型
export class EmployeeViewModel extends PersonViewModel<IEmployeeViewModel> implements IEmployeeViewModel {
    constructor(role: string, name: string) {
        super(name);
        this.role = role;
    }
    public role: string;

    public setRole(value: string): IEmployeeViewModel {
        const vm = { ...this, role: value };
        return vm;
    }
}

该方案的使用效果和方案1完全一致,适合需要对返回类型做额外定制的场景。

内容的提问来源于stack exchange,提问作者user8607541

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 02:30:01