Reputation: 2721
Classes are a bit weird in typescript, in that they seem to be both actual "things" (functions in this case) and typescript types at same time.
Example:
class Test {
public x: string = 'test';
}
function printX(test: Test) {
console.log(test.x);
}
function createTest() {
return new Test();
}
Notice how I can say printX
takes an argument of type Test
, but also use Test
as a value in createTest()
method. So the same symbol "Test
" is acting as both a value and a type.
How can I recreate the same kind of construct without using the obvious class
keyword?
For example:
function makeTestClass() {
return class Test {
public x: string = 'test';
};
}
const Test = makeTestClass();
function printX(test: Test) {
console.log(test.x);
}
function createTest() {
return new Test();
}
This code will not compile because typescript will think Test
is a value, not a type.
So is there some way I can tell typescript Test
is actually the magical dual type/value thing you get using the class
keyword?
Upvotes: 1
Views: 61
Reputation: 8340
I believe the closest one fulfilling your requirements you may get with something like that:
interface Test {
x: string
}
const Test = function Test(this: Test){
this.x = 'string' as string
return this
} as unknown as { new (): Test }
function printX(test: Test) {
console.log(test.x);
}
function createTest() {
return new Test();
}
Here we're defining interface Test
(type level) for values of our class' instances. And the constructor function Test
(value level) for creating our instances. Since functions do not have constructor signature baked in we have to assert (as unknown as { new (): Test }
) typescript that this function still can be used as a constructor with new
keyword.
This function still lacks a lot of functionality of a real class
. It does not support inheritance and cannot setup private (in typescript sense) members or methods. Also keep in mind that interfaces also cannot fully mimick class
instances. As they cannot describe private
members or methods too.
Upvotes: 2