これはなに
- 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;
}