Skip to main content

Command Palette

Search for a command to run...

Extending multiple classes in TypeScript

Updated
•2 min read•View as Markdown
Extending multiple classes in TypeScript

If you tried to extend multiple classes, you know you can't do something like

export class ChildClass extends ParentClass, GrandParentClass {}

without getting an error that you can extend only one class

But, you can do something like this

const ExtendedParent = class ParentClass extends GrandParentClass {}
export class ChildClass extends ExtendedParent {}

Now, let's do a mixin that will automagically do the extensions for you, no matter how many classes you need to extend.

class ClassExtenderMixin {
  private superclass: any;

  constructor(superclass: any) {
    this.superclass = superclass;
  }

  with(...otherClassesMixins: any[]) {
    return otherClassesMixins.reduce((extendedClass, classMixin) => classMixin(extendedClass), this.superclass);
  }
}

export default (superclass: any) => new ClassExtenderMixin(superclass);

You call this mixin where you want to extend a class, like so:

import extendClass from 'class.extender.mixin';

export default class ChildClass extends extendClass(ParentClass).with(GrandParentClassMixin, GrandGrandParentClassMixin, etc)

And you need to define the other classes mixin as so:

export default (superclass: any) => class extends superclass { // the content of GrandParentClass } 

What happens with the ClassExtenderMixin is:

  1. when you call extendClass(ParentClass), you make the ParentClass as the superClass of the new returned class; so you have something like:
const ParentClassToExtend = extendClass(ParentClass)
// this translates to
const ParentClassToExtend = new ClassExtenderMixin(ParentClass)

export default ChildClass extends ParentClassToExtend {}
  1. next, you call the ParentClassToExtend with method, which takes the other classes mixins functions with the current class you are passing as arguments; Note that in the with's arguments, you transform the arguments in an array, with the rest parameters and that's why you can call reduce on the method arguments.
// at first iteration, you call the mixin function and assign the extendedClass as
// class extends ParentClass; let's call this ExtendedParentClass
// this happens, because GrandParentClassMixin is defined as (superclass) => class extends superclass {}

// at second iteration, you call the mixin function assign the extendedClass as
// the class extends ExtendedParentClass
// this happens because GrandGrandParentClassMixin is also defined as (superClass) => class extends superclass {}

// and so on, if you have multiple extender mixins

You can use this method for extending an AbstractClass with SomeSpecificMethodsClass and SomeOtherSpecificMethodsClass

Note, I took this pattern from JavaScript. There is also another pattern for extending classes in TypeScript.