Reputation: 699
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
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
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
Reputation: 30686
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;
}
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");
});
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
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...
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