user1137582
user1137582

Reputation: 699

Typescript anonymous class

Is there a way in typescript to create anonymous class?

my code:

export abstract class Runnable {
    public abstract run();
}

and I'm trying to do something like this:

new Runnable {
    runner() {
        //implement
    }
}

How can I do it?

Upvotes: 62

Views: 46914

Answers (4)

Hossain Khademian
Hossain Khademian

Reputation: 1696

You just need to create an inline local class and immediately extend it.

interface Runnable {
    run();
}

// ...

const runnable = new (class ___Runnable implements Runnable {
    run() { /*...*/ }
});

/* parentheses are optional */

return new class ___Runnable implements Runnable {
    run() { /*...*/ }
}

/* do not worry, ___Runnable does not leak in to scope.
its scope is the hidden (extra) parentheses. */

Upvotes: 1

Michal
Michal

Reputation: 1163

Yes, here is the way.

The abstract class:

export abstract class Runnable {
  public abstract run();
}

An anonymous implementation:

const runnable = new class extends Runnable {
  run() {
    // implement here
  }
}();

Upvotes: 101

holi-java
holi-java

Reputation: 30686

How to create Anonymous Class?

Let's say you have a interface Runnable and an abstract class Task.when you declare a class Foo in typescript you actual create an class instance of Foo & a constructor function for the class Foo.you could want to see depth in typescript.Anonymous class that ref as a constructor function like {new(...args):type} that can be created using new keyword.

interface Runnable {
    run(): void;
}

abstract class Task {
    constructor(readonly name: string) {
    }

    abstract run(): void;
}

Create anonymous class extends superclass via class extends ?

test('anonymous class extends superclass by `class extends ?`', () => {
    let stub = jest.fn();
    let AntTask: {new(name: string): Task} = class extends Task {
        //anonymous class auto inherit its superclass constructor if you don't declare a constructor here.
        run() {
            stub();
        }
    };

    let antTask: Task = new AntTask("ant");
    antTask.run();

    expect(stub).toHaveBeenCalled();
    expect(antTask instanceof Task).toBe(true);
    expect(antTask.name).toBe("ant");
});

create anonymous class implements interface/type via class ?.

test('anonymous class implements interface by `class ?`', () => {
    let stub = jest.fn();
    let TestRunner: {new(): Runnable} = class {
        run = stub
    };

    let runner: Runnable = new TestRunner();
    runner.run();

    expect(stub).toHaveBeenCalled();
});

Upvotes: 9

Nitzan Tomer
Nitzan Tomer

Reputation: 164147

Not quite, but you can do this:

abstract class Runnable {
    public abstract run();
}

let runnable = new (class MyRunnable extends Runnable {
    run() {
        console.log("running...");
    }
})();

runnable.run(); // running...

(code in playground)

The problem with this approach however is that the interpreter will evaluate the class every time it uses it, unlike with a compiled language (such as java) in which the compiler only evaluates it once.

Upvotes: 26

Related Questions