Reputation: 913
I want a class that behaves like js Date function:
new
it creates an instance of class.How do i implement this interface?
interface A {
(): string;
new(arg: number);
GetValue(): number;
}
current solution that doesn't compile but produces correct js code in playground:
class B implements A {
private Value: number;
constructor(arg: number) {
if (this.constructor == B) {
this.Value = arg;
} else {
return "42";
}
}
GetValue(): number {
return this.Value;
}
}
Upvotes: 0
Views: 298
Reputation: 329533
You can't use an ES2015 or later class
to let you call a constructor without the new
keyword. In Step 2 of Section 9.2.1 of the linked documents, calling a class constructor without the new
keyword should result in a TypeError
being thrown. (If you target ES5 in TypeScript you'll get something that works at runtime, but if you target ES2015 or above you will get runtime errors. It's best not to do this.) So to implement your interface you will need to use a pre-ES2015 constructor function instead.
By the way, the new(arg: number)
signature needs a return type. For example:
interface A {
(): string;
new(arg: number): AInstance; // return something
GetValue(): number;
}
// define the instance type
interface AInstance {
instanceMethod(): void;
}
Here's one way to implement that. First, make a class
for AInstance
:
class _A implements AInstance {
constructor(arg: number) { } // implement
instanceMethod() { } // implement
}
Then, make a function that can be called with or without new
:
const AFunctionLike =
function(arg?: number): AInstance | string {
if (typeof arg !== "undefined") {
return new _A(arg);
}
return "string";
} as { new(arg: number): AInstance, (): string };
I've decided that if you call AFunctionLike
with an argument then you will get an AInstance
, otherwise you will get a string
. You can also check explicitly for whether new
was used, via new.target, if your runtime has support for it.
Also note that I had to assert that AFunctionLike
is newable (with the as
clause on the last line) since there's currently no other way to tell TypeScript that a standalone function can be called with new
.
Now we're almost done. We can declare a value of type A
as follows:
const A: A = Object.assign(
AFunctionLike,
{
GetValue() {
return 1;
}
}
);
The value A
has been formed by merging AFunctionLike
with an object that implements GetValue()
. You can use Object.assign
or spread syntax to do this merging.
That's it. You can verify that this works at runtime on the TypeScript Playground. Good luck!
Upvotes: 2