0

I'm trying to pick up some TypeScript knowledge for my work, and I just realized that the implementation of method overriding in a derived class is different from other static typed languages such as Java.

For example, I realized I can do this in TS:

class Base {
    constructor(greet: string){
        console.log('base', greet);
    }

    getExample(arg1: unknown): unknown{
        console.log('base getExample', arg1);
        return ''
    }
}

class Derived extends Base{
    constructor(){
        super('Hello');
    }

    getExample(arg1: string): string{
        console.log('derived getExample', arg1);
        return 'something'
    }

    getExample2(arg1: string): string{
        console.log('derived getExample2', arg1);
        return '2'
    }
}

const doj: Base = new Derived();
doj.getExample(123); // derived getExample 123
doj.getExample('123'); // derived getExample “123”
(doj as Derived).getExample2('123');

I'm wondering why is the getExample in the Derived class overridden not overloaded(the argument type and return type are different from the getExample in the Base class)?

I can't find what the rules of method overriding are in the TS handbook, hope I can get help here. Many thanks.

Nicholas
  • 43
  • 4
  • There is no overloading in JavaScript and by extension, TypeScript. Any function/method with the same *name* overwrites the previous one. Regardless of the number and the type of parameters it takes.See [Overloads](https://www.typescriptlang.org/docs/handbook/functions.html#overloads) and [Do's and Don'ts - Overloads and Callbacks](https://www.typescriptlang.org/docs/handbook/declaration-files/by-example.html#overloaded-functions) – VLAZ Nov 08 '20 at 16:11
  • Thanks for your answer, but why did 'doj.getExample(123);' work, and print 'derived getExample 123'? the formal argument is of type string but the actual argument is of type number. this is really confusing to me. – Nicholas Nov 08 '20 at 16:25
  • Because you're calling it off something that's of type `Base`, therefore the signature you have is `getExample(arg1: unknown): unknown`. A number is assignable to `unknown` ([as is any other type](https://stackoverflow.com/questions/51439843/unknown-vs-any)), therefore, you're allowed to call `baseObj.getExample(123)`. Remember that the type system *only* exists at compile time - [there is no type checking at runtime](https://github.com/microsoft/TypeScript/wiki/FAQ#what-is-type-erasure). – VLAZ Nov 08 '20 at 16:41
  • Perfect! That makes sense to me now. Thanks @VLAZ! My last question tho, when you said "TypeScript. Any function/method with the same name overwrites the previous one. Regardless of the number and the type of parameters it takes", it didn't seem like the case, as in if I have the argument arg1 declared of type number for the getExample method in the Base class, and string in the Derived class, the compiler will throw an error. – Nicholas Nov 08 '20 at 17:24
  • Because that's how JavaScript works. Two properties or functions sharing the same name are just overwriting each other. The TypeScript compiler will prevent *some* instances of this but it only checks whether the new method signature is assignable to the old one. So you *could* have `getExample(arg: Animal)` in `Base` and `getExample(arg: Cat)` in `Derived`. `(arg: Cat) => {}` is assignable to `(arg: Animal) => {}` but `(arg: Cat) => {}` isn't assignable to `(arg: Dog) => {}`. See [here](https://www.typescriptlang.org/docs/handbook/2/functions.html#assignability-of-functions). – VLAZ Nov 08 '20 at 18:01
  • So, since `(arg: string) => string` is assignable to `(arg: unknown) => unknown` the TS compiler allows it. This *does* mean that you can have cases where you might call the wrong thing - if `Derived1` expects a string and `Deriver2` a number but you only have `Base` you might call your method with the wrong value. Also, TS is unsound in that it has [bivariant function parameters](https://github.com/microsoft/TypeScript/wiki/FAQ#why-are-function-parameters-bivariant). In short, not only is `(arg: Cat) => {}` is assignable to `(arg: Animal) => {}` but also vice versa. – VLAZ Nov 08 '20 at 18:01
  • Marvellous! Now I get it. Thank u so much @VLAZ! – Nicholas Nov 09 '20 at 00:47

0 Answers0