LoginSignup
21

More than 5 years have passed since last update.

TypeScriptで型の異なるメソッドをオーバーライドする

Last updated at Posted at 2016-04-05

これはなに

  • TypeScriptでは親クラスのメソッドを継承する際、オーバーライド(同名メソッドの上書き)ができる
  • ただし、引数や返り値の型の異なる場合はオーバーライドできない
  • オーバーロード宣言と組み合わせる事で実現できる

前提:引数や返り値の型の異なるメソッドはオーバーライドできない

TypeScriptは(、元のES2015の仕様に合わせ)特に何の宣言も不要でメソッドのオーバーライドができる。ただしJSと異なるのは引数や返り値の型のチェックが入るため、一致しないとオーバーライドできない12

引数の型が異なるのでオーバーライドできない
class Base{
    method(arg:string){}
}

//error! Type of property 'method' are incompatible.
class ChildA extends Base{
    method(arg:number){}
}

対処法:オーバーロード宣言と組み合わせる

TypeScriptには同名メソッド・関数で引数・返り値の型や数などが異なる時用に、オーバーロードがある。

これをつかい、子クラス側で①継承元と同じ型のメソッドと②新しいメソッドをオーバーロードで宣言すればエラーにならず、継承できる。


class Base{
    method(arg:string){}
}

//ok
class ChildB extends Base{
    method(arg:number):void;    //②
    method(arg:string):void;    //①
    method(arg:any){
        if(typeof arg === "string"){
            super.method(arg);
        }else if(typeof arg === "number"){
            //...
        }
    }
}

親クラスと同じ型を拒否

親クラスと同じ型の引数だった場合を拒否するには、TSの型システムではできない。やるなら、以下のようにランタイムにチェックする。

class ChildB extends Base{
    method(arg:number):void;
    method(arg:string):void;
    method(arg:any){
        if(typeof arg === "string"){
            throw TypeError(`Invalid type of argument. typeof arg: ${typeof arg}`);
        }else if(typeof arg === "number"){
            //...
        }
    }
}

参考:型定義

既存ライブラリ用に型定義ファイルを書くなら以下のようになる。

*.d.ts
declare class Base{
    method(arg:string):void;
}

//ok
declare class ChildB extends Base{
    method(arg:string):void;
    method(arg:number):void;
}

  1. C++/Java/C#も同様。 

  2. なお、基底クラスのメソッドをprivateで宣言していてもダメ。 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21