Skip to content

Allow expressions in class extends clauses - #3516

Merged
Anders Hejlsberg (ahejlsberg) merged 18 commits into
masterfrom
extendsExpressions
Jun 17, 2015
Merged

Allow expressions in class extends clauses#3516
Anders Hejlsberg (ahejlsberg) merged 18 commits into
masterfrom
extendsExpressions

Conversation

@ahejlsberg

Copy link
Copy Markdown
Member

This PR allows the extends clause of a class to specify an arbitrary expression that computes a constructor function. The PR also relaxes the strict requirement that extends specify a class type and instead allows expressions of "class-like" constructor function types. This means that built-in types can now be extended in class declarations.

The extends clause of a class previously required a type reference to be specified. It now accepts an expression optionally followed by a type argument list. The type of the expression must be a constructor function type with at least one construct signature that has the same number of type parameters as the number of type arguments specified in the extends clause. The return type of the matching construct signature(s) is the base type from which the class instance type inherits. Effectively, this allows both real classes and "class-like" expressions to be specified in the extends clause.

Some examples:

// Extend built-in types

class MyArray extends Array<number> { }
class MyError extends Error { }

// Extend computed base class

class ThingA {
    getGreeting() { return "Hello from A"; }
}

class ThingB {
    getGreeting() { return "Hello from B"; }
}

interface Greeter {
    getGreeting(): string;
}

interface GreeterConstructor {
    new (): Greeter;
}

function getGreeterBase(): GreeterConstructor {
    return Math.random() >= 0.5 ? ThingA : ThingB;
}

class Test extends getGreeterBase() {
    sayHello() {
        console.log(this.getGreeting());
    }
}

Fixes #511.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The best way to handle all these changes is to tweak typeWriter to produce results like what we used to get. Then, we can actually review the handful of files that have relevant changes. Then, once we can see that nothing else changed unintentionally, we can remove that tweak in a followup change and then update all the baselines. With several hundred files changed, github won't show all the changes. And it becomes very difficult to ascertain if something else might have broke as part of this.

We've done this numerous times as we've changed hte compiler. For example, even when moving over from the old compiler to the new one, we tweaked things in the new typewriter to produce the same output as hte previous one.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a workaround to reduce the number of changes, but it isn't possible to completely eliminate the differences. Should be a lot better now, though.

@ahejlsberg

Copy link
Copy Markdown
Member Author

Mohamed Hegazy (@mhegazy) Jason Freeman (@JsonFreeman) Cyrus Najmabadi (@CyrusNajmabadi) I'd like to get this one in pretty soon. I will be putting up a separate CR with the change to __extends to permit the base class to be null since it generates a lot of differences.