Can I change return type of method in extended class?

Viewed 1597

I need class B extend interface C, however I would like to use implementation of A::methodA to calculate result of B::methodA.


interface C {
  methodA(): number
}

class A {
  methodA(): string {
    return '42'
  }
}

class B extends A implements C {
  methodA(): string {
    return Number(super.methodA()).
  }
}

Can I use implementation of class A with inheritance or is association my only hope?

4 Answers

you can define the return type of method A() on interface C to number | string, it has to be a compatible return type.

interface C {
  methodA(): number | string
}

class A {
  methodA(): string {
    return '42'
  }
}

class B extends A implements C {
  methodA(): string {
    return super.methodA();
  }
}

EDIT: so considering your scenario below, it might not be the best solution but you could use the utility type Omit and create a new type from C to avoid the validation of method1 (more examples here)

interface C {
  methodA(): number
  //methodB(): string,
  //methodC(): number
  //..
}
type C1 = Omit<C, "methodA">;

class A {
  methodA(): string {
    return '42'
  }
}

class B extends A implements C1 {
  methodA(): string {
    return super.methodA();
  }
}

You may make the methodA in class A return type any instead of string.

interface C {
   methodA(): number
}

class A {
  protected methodA(): any {
    return '42'
  }
}

class B extends A  implements C {
    methodA(): number {
      return Number(super.methodA());
  }
}

When developing software using OO constructs (such as inheritance) you should be mindful of the SOLID principles. These principles aim to make your code more understandable, flexible, and maintainable. They are broadly considered to be best practice.

So, while you can use the workarounds suggested by previous answers (e.g. union types) to permit a different return type in the overridden method ... You should consider whether this results in clear, maintainable code.

In particular, doing this may violate the Liskov substitution principle, which states that:

"Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program."

In javaScript we are likely talking about inheritance between Objects and not classes, Here's a simple implementation of your example this using Prototype

class A {
    constructor (){}
    methodA() {
        return '42'
    }
}

class B extends A{
    constructor (){
        super();
    } 
    methodA(){};
}

b = new B();
a = new A();

B.prototype.methodA = function (nbr){ return 1 * nbr};
console.log("B " + b.methodA('4'))
Related