声明(定义)类成员方法

时间:2017-01-17 22:47:28

标签: typescript es6-class

我有TypeScript ES6 Class,假设它看起来像这样

class Classic
    private _member: Object;
    constructor(member: Object) {
       this._member = member;
    }
}

我有一些富有的对象,它包含很多方法,我想继承,但该对象不是TS或ES6类,它只是POJO(ObjectLiteral)。

所以我做了快速而又脏的继承,比如

Object.assign(Classic.prototype, ObjectLiteralWithMethods);

无需深层复制,一切正常。

如何告诉TypeScript Classic具有这些继承的方法并指定其行为?

我搜索了诸如声明或定义AND类AND方法之类的关键字,但我的google-fu还不够。

我尝试为Classic定义界面,但它也不起作用。

我试图声明类似

declare class ObjectLiteralWithMethods {
    public method(): void;
    protected _method(parameter: string): void;
}

然后将该声明扩展为

class Classic extends ObjectLiteralWithMethods { ... }

但是然后TypeScript要我在super()中调用constructor,但失败了。

我知道我可以在Classic上实现“虚拟”方法,如

class Classic {
    dummyMethodImplementation(param: string): string {
        return param;
    }
}

但这将是痛苦和低效的。我只想定义/声明类Classic已扩展。

解决

排序......

我的案例中的ObjectLiteralWithMethods实际上是jQuery小部件的原型。所以,我扩展了原型的所有者。

它需要一些补丁,因为TS不知道所有者所以我做了:

// declaring the properties and methods which will be inherited by my class
declare class JQueryUIWidget {
    public property: string;
    public method(): string;
    ...
}

// must declare a constructor for JQueryUIWidget to be able to extend
// and cast the value to any, so TS do not mind
const Widget: { new (): JQueryUIWidget } = $.Widget as any;

// and then extend that declaration
class Classic extends Widget {
    constructor() {
        super(); // super(); is mandatory here, with plain object it 
                 // did not worked, but since Widget is in fact a Function
                 // it works now
    }
}

2 个答案:

答案 0 :(得分:0)

你可以这样做:

declare class ObjectLiteralWithMethods {
    public method(): void;
    public _method(parameter: string): void;
}

class Classic implements ObjectLiteralWithMethods {
    private _member: Object;

    constructor(member: Object) {
       this._member = member;
    }

    method: () => void;
    _method: (parameter: string) => void;
}

code in playground

但您无法在ObjectLiteralWithMethods中使用受保护的成员/方法,因为您将其用作界面。

修改

如果您需要覆盖子类中Classic中的方法,那么您需要使用stabs来实现这些方法:

class Classic implements ObjectLiteralWithMethods {
    private _member: Object;

    constructor(member: Object) {
       this._member = member;
    }

    method() {};
    _method(parameter: string) {}
}

class Other extends Classic {
    method() {

    }
}

Classic中的方法为空,您可以使用ObjectLiteralWithMethods中的实现覆盖它们。

答案 1 :(得分:0)

有点晚了,但是当将遗留系统的一部分转换为TypeScript时,我有一个类似的要求,因此这可能对其他人有所帮助。

如果您知道您的类将在运行时使用其他方法进行增强,并且您只想为这些方法提供类型信息和智能感知,并且您不想编写难看的存根,则可以尝试以下操作:

首先,定义详细描述运行时方法的接口:

interface RuntimeImplementedType {
    public method(): void;
}

interface AnotherRuntimeImplementedType {
    public other_method(): void;
}

然后定义一个变量,将其类型指定为构造函数,以返回要通知TypeScript您的类在运行时实现的类型的并集。为变量分配一个函数,该函数返回一个空对象文字,并将其转换为“ any”,以避免编译器抱怨,并确保在编译时实际上扩展的对象只是一个普通的旧空对象。

const Base: new() => RuntimeImplementedType & AnotherRuntimeImplementedType = (() => {}) as any;

现在定义新类,从构造函数的变量开始扩展:

class Classic extends Base {
    public doSomething() {
        this.method();
        this.other_method();
    }
}

接口中的所有方法都应该可用,但不必实际提供实现。