I like Object oriented programming (oop
), and inheritance, but it can be painful at times when you can't express yourself fully.
Typing things in typescript can be tricky.
I often like to use static class initializers (useful for async operations), but I've been struggling with how to inherit initializers. I figured it out and thought I'd put it somewhere for safe keeping.
class Foo {
constructor (public props?: {
alpha?: boolean
}) {}
static init <T extends typeof Foo>(this: T, props?: ConstructorParameters<T>[0]): InstanceType<T> {
return new this(props) as InstanceType<T>;
}
}
class Bar extends Foo {
constructor (public props?: NonNullable<ConstructorParameters<typeof Foo>[0]> & {
beta?: boolean
}) {
super();
}
static init <T extends typeof Bar>(this: T, props?: ConstructorParameters<T>[0]): InstanceType<T> {
return new this(props) as InstanceType<T>;
}
}
const x = Foo.init({ alpha: true })
const y = Bar.init({ alpha: true, beta: true })
Here you can see that we have Foo
and Bar
they both have their own init
method, that returns their respective class instances.
We can further expand on this.
Taking this another step further, we may want to extend the parent's init
method, and run it was well. This allows us to chain the encapsulated / replaced functionality through to the children classes.
class Foo {
constructor (public props?: {
alpha?: boolean
}) {}
dogs?: boolean;
init () {
this.dogs = true;
return this;
}
static init <T extends typeof Foo>(this: T, props?: ConstructorParameters<T>[0]): InstanceType<T> {
const t = new this(props) as InstanceType<T>;
this.init();
return t;
}
}
class Bar extends Foo {
constructor (public props?: NonNullable<ConstructorParameters<typeof Foo>[0]> & {
beta?: boolean
}) {
super();
}
cats?: boolean;
init () {
super.init();
this.cats = true;
return this;
}
static init <T extends typeof Bar>(this: T, props?: ConstructorParameters<T>[0]): InstanceType<T> {
const t = new this(props) as InstanceType<T>;
t.init();
return t;
}
}
const y = Bar.init({ alpha: true, beta: true })
console.log(y.dogs);
This is one trick we can add to the typescript oop
toolbox, to fully express ourselves better.
Top comments (0)