Skip to content

Feature suggestion: treat prototype assignments like merging type declarations #4038

Closed
@ghost

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 }

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.SuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions