
Description
I would like better native support for code of this nature:
function impl1() { // implementation A for myVirtualMethod
this.x = 1; // this is treated as global object or any
}
function impl2() { // implementation B for myVirtualMethod
this.y = 1; // no type-safety, compiler doesn't know what 'this' will be bound to.
}
export class Base {
public myVirtualMethod() {}
public x: number;
}
export class Derived1 extends Base {
// can't assign function to myVirtualMethod here to override method
}
Derived1.prototype.myVirtualMethod = impl1; // override method with function
export class Derived2 extends Base {}
Derived2.prototype.myVirtualMethod = impl2; // override method with function
The code above works, but has a couple of drawbacks, which I think are resolvable:
The compiler has no way of knowing what this
pointer should be in impl1
and impl2
- I would like a way to redefine what type
this
is for functions. - It would also be nice if the compiler could detect if this contract is not honored (e.g., the function is invoked without a receiver, or is assigned to a method on a class which does not match the interface)
- Possibly infer an interface for the receiver of the function if none is declared
Possible syntax:
function impl1() overrides Base.myVirtualMethod {}
function impl1(): this implements Base {}
function impl1() { const this: Base; }
The compiler won't let you define a method by assigning a function, so you must assign to the prototype instead
- It may be nice to have a way to designate that certain properties are intended to be assigned to the prototype, from inside the class body
- I would like way to declare a method but define the body through assignment
Possible syntax:
public myVirtualMethod() = impl1; // Parentheses distinguish this from a property assignment.
public myVirtualMethod() = null; // pure virtual method (runtime error to invoke, no compile time check)
Type checking:
impl1(); // Type error: Window does not implement { x: number }
this.y = 1; // Type error: Base does not implement { y: number }
public myVirtualMethod() = impl2; // Type error: Derived1 does not implement { y: number }
impl2.call( new Derived1 ); // Type error: Derived1 does not implement { y: number }