I want to be able to initialise a class with or without value. If you pass a value then all methods of this class will expect this value as an argument and the value will be of the type you passed with initialisation.
If you pass nothing then methods are not going to expect any arguments and the value will be undefined.
I think some code will make a better example:
class Foo<T = void> {
constructor(public type?: T) {}
bar = (type: T) => {
if (type) {
this.type = type;
}
};
}
const fooUndefined = new Foo();
fooUndefined.bar(); // no errors, this is ok
fooUndefined.type === undefined; // no errors, this is ok
fooUndefined.bar(1); // expected error, this is ok
const fooNumber = new Foo(0);
fooNumber.type === 1; // no errors, but type is `number | undefined`, this is not ok
fooNumber.type > 0; // unexpected error because type is `number | undefined`, this is not ok
fooNumber.bar(1); // no errors, this is ok
fooNumber.bar(); // expected error, need to pass number, this is ok
fooNumber.bar('1'); // expected error, strings are not acceptable, this is ok
const fooUnion = new Foo<'a' | 'b'>() // no error, unexpected because it should not allow it
fooUnion.type.charAt(0) // unexpected error
const fooUnion2 = new Foo<'a' | 'b'>('c') // expected error, this is ok
fooUnion2.type.charAt(0) // unexpected error
So the type property in fooNumber example is of type number | undefined. Is there a way to narrow it to number without explicit typecasting?