Typescript abstract optional method

Viewed 23756

I have an abstract class with some abstract methods. Is there a way to mark some of these methods as optional?

abstract class Test {
    protected abstract optionalMethod?(): JSX.Element[];
    protected abstract requiredMethod(): string;
}

For some reasons I can add the ? as a suffix but it seems like it does nothing at all because I have to still implement the method in the derived class. For now I am using it like this to mark it that it can return null which is basically the poor mans optional.

protected abstract optionalMethod?(): JSX.Element[] | null;
6 Answers

You can do this with class and interface merging:

interface Foo {
   print?(l: string): void;
}

abstract class Foo {
  abstract baz(): void;

  foo() {
    this.print && this.print('foo');
  }
}

class Bar extends Foo {
  baz(): void {
    if (this.print) {
      this.print('bar');
    }
  }
}

Link to the above code in the Typescript playground

I'm not sure if this changed at some point, but today (TS 4.3) you can simply make the base-class optional method non abstract:

abstract class Base {
    protected abstract required(): void;
    protected optional?(): string;

    print(): void {
        console.log(this.optional?.() ?? "Base");
    }
}

class Child1 extends Base {
    protected required(): void { }
}

class Child2 extends Base {
    protected required(): void { }
    protected optional(): string {
        return "Child";
    }
}

const c1 = new Child1();
c1.print();

const c2 = new Child2();
c2.print();

Try it on the TS Playground.

Typescript doesn't support the "omission" of optional abstract functions, but you can explicitly leave it undefined as below:

abstract class Test {
    protected abstract optionalMethod?(): JSX.Element[];
    protected abstract requiredMethod(): string;
}

class MyTest extends Test {
    protected optionalMethod: undefined;

    protected requiredMethod(): string {
        return 'requiredResult';
    }
}

This has been around for a while but and answered correctly above, but the example isn't clear. You can use interface merging like this too.

interface Test {
    optionalMethod?(): JSX.Element[];
}

abstract class Test {
    protected abstract requiredMethod(): string;
}

You don't need interface merging. You only have to work with overload methods without default implementations like so:

abstract class Test {
    ...
    private someMethod() {
       ...
       this.optinalMethod?.();
    }
    ...
    protected abstract requiredMethod(): string;
    protected optionalMethod?(): string;
}

abstract indicated that it has to be overwritten in the implementing class. in case of an optional method we however don't want to enforce overriding it.

Related