Mic*_*and 10 javascript inheritance typescript
我有一个要扩展的基类:
export class BaseClass<T extends SomeOtherClass> {
constructor(param: ParamType) {
}
doSomething(param1: Param1Type): BaseClass<T> {
// do something with param1;
return this;
}
}
Run Code Online (Sandbox Code Playgroud)
我的课:
export class MyClass<T extends SomeOtherClass> extends BaseClass<T> {
constructor(param: ParamType) {
super(param);
}
doSomething(param1: Param1Type, param2: Param2Type): MyClass<T> {
// super.doSomething(param1);
// do something with param2;
return this;
}
}
Run Code Online (Sandbox Code Playgroud)
但我收到警告:
Property 'doSomething' in type 'MyClass<T>' is not assignable to the same property in base type 'BaseClass<T>'.
Type '(param1: Param1Type, param2: Param2Type) => MyClass<T>' is not assignable to type '(param1: Param1Type) => BaseClass<T>'.
Run Code Online (Sandbox Code Playgroud)
不能在打字稿中扩展方法签名吗?如果我需要向重写的方法添加一个参数,我如何扩展 BaseClass 的功能,这是在 es6 语法中调用父方法的正确方法。我知道在 es6 之前我可以调用 BaseClass.prototype.doSomething.call(this, param1)。
其他人指出的问题是,如果param2需要,它会破坏多态性:
// We should be able to do this assignment
let baseRef: BaseClass<SomeOtherClass> = new MyClass<SomeOtherClass>("");
baseRef.doSomething("") // param2 is not required by the base class so MyClass will not receive it even though it NEEDS it
Run Code Online (Sandbox Code Playgroud)
一种解决方案是将第二个参数设为可选,因此该调用baseRef.doSomething("")对于派生类型也有效:
export class MyClass<T extends SomeOtherClass> extends BaseClass<T> {
constructor(param: string) {
super(param);
}
doSomething(param1: string, param2?: string): MyClass<T> {
super.doSomething(param1);
return this;
}
}
Run Code Online (Sandbox Code Playgroud)
第二种解决方案,如果我们只想在类之间共享代码,则let baseRef: BaseClass<SomeOtherClass> = new MyClass<SomeOtherClass>("");通过不真正继承BaseClass而是继承排除该doSomething方法的类来禁止赋值:
type PartialBaseClass = new <T> (param: string) => { [P in Exclude<keyof BaseClass<T>, 'doSomething'>] : BaseClass<T>[P] }
const PartialBaseClass:PartialBaseClass = BaseClass
export class MyClass<T extends SomeOtherClass> extends PartialBaseClass<T> {
constructor(param: string) {
super(param);
}
doSomething(param1: string, param2: string): MyClass<T> {
BaseClass.prototype.doSomething.call(this, param1);
return this;
}
}
// This is now invalid !
let baseRef: BaseClass<SomeOtherClass> = new MyClass<SomeOtherClass>("") ;
Run Code Online (Sandbox Code Playgroud)