implements/interface/type/extendsの違い【TypeScript】

自分用のメモ。

  • interface:オブジェクト、クラス、関数の型のみを宣言する
  • type:どんな型でも宣言する
  • extends:継承する
  • implements:実装する

interfaceとtypeはすごく似てるので正直どちらを使っても良いっぽいです。

extends

例えば、冒険者(Adventurer)というclassがあるとします。

class Adventurer{
  name:string
  hp:number
}

冒険者は名前とHPを持っています。

 

冒険者は別の職業にジョブチェンジできます。

ここでは冒険者→魔法使い(Wizard)にジョブチェンジするものとするとして、Wizardクラスを作るとすると以下のようになります。

//WizardクラスはAdventurerを継承しているのでhpとnameプロパティも持っている
class Wizard extends Adventurer {
  mp: number
}

このとき使うのがextends

  • extendsを使うと冒険者のプロパティをすべて継承する
  • つまり冒険者⊂魔法使いみたいな関係になる

 

new演算子を使って、実体化(インタンス化)します。

//ハリーポッターを作る
const HarryPotter = new Wizard();

interface

interfaceは、オブジェクト・関数・クラスの構造を決めるためのもの。

要するに「このオブジェクトはこういう構造だぜ!」を決めるためのもの。

 

例えば、以下のような「空を飛べるよ!」なinterfaceを作ります。

interface flyable {
  icanfly(): void
}

このinterfaceを実装されたクラスは空を飛べるようになります。

 

例えば、以下のようにWizardクラスにflyableを実装します。

class Wizard extends Adventurer implements flyable {
  mp: number
  icanfly(){
    console.log("空を飛ぶよ!")
  }
}

 

このようにinterfaceを実装するには、implementsを使います。

ところで「構造を決めるためのもの」と言いつつ、関数を1つしか実装していないじゃないか!と思うかもですが、それは説明しやすくするためでございます。。

extends

extendsを使うとinterfaceからinterfaceへ継承できます。

例えば「瞬間移動できるよ!」なinterfaceを作りたいとします。

ただし「瞬間移動」のスキルを身につけるには、「空を飛ぶ」スキルを先に身につけておかないといけないとしましょう。瞬間移動は空を飛ぶスキルの上位互換なのです。

そうすると、以下のように継承できます。

//空を飛べるよ!なinterface
interface flyable {
  icanfly(): void;
}

//瞬間移動できるよ!なinterface
interface teleportable extends flyable {
  icanteleport(): void;
}

 

このとき、teleportableinterfaceを実装されたWizardクラスは、

  • icanfly()
  • icanteleport()

の両方のスキルを持つ必要があります。

class Wizard extends Adventurer implements teleportable {
  mp: number;
  icanfly() {
    console.log("空を飛ぶよ!");
  }
  icanteleport() {
    console.log("瞬間移動するよ!");
  }
}

type

typeの正式名称は「Type Aliases」。

要するに「あだ名をつけるぜ!」な機能。

 

例えば、以下のような「空を飛べるぜ!」なtypeを作ります。

type flyable= {
  icanfly(): void
}

このtypeを実装されたクラスは空を飛べるようになります。

 

例えば、以下のようにWizardクラスにflyableを実装します。

class Wizard extends Adventurer implements flyable {
  mp: number
  icanfly(){
    console.log("空を飛ぶよ!")
  }
}

interfaceとtypeの違い

「あれ?interfaceと同じじゃね?」と思うかもですが、大体そのとおりです

ですが厳密にいうと

  • typeは宣言のときに=が必要だけど、interfaceは不要
  • typeextendsで継承できないが、交差型と呼ばれる機能で似たようなことができる
  • 同名のtypeを宣言するとエラーになるが、同名のinterfaceを宣言するとマージされる
  • typeはプリミティブ、配列、タプルなども宣言可能だけど、interfaceはオブジェクトと関数のみ宣言可能

という感じで色々違うみたいです。このページでは詳しく説明しないので別のサイトでお調べください。

implements

例えば、冒険者というジョブを持つ人が存在しない場合、冒険者はinterfacetypeとして作っておき、「魔法使いなどの他の職業は冒険者を実装する」みたいな形にもできます。

interface Adventurer {
  name: string;
  hp: number;
}

class Wizard implements Adventurer {
  name: string;
  hp: number;
  mp: number;
}

まとめ

  • classimplementsできるのは・・・
    classtypeinterface
  • classextendsできるのは・・・
    classのみ
  • typeimplementsできるのは・・・
    classtypeinterface
  • typeextendsできるのは・・・
    →なし
  • interfaceimplementsできるのは・・・
    classtypeinterface
  • interfaceextendsできるのは・・・
    interfacetype

 

「typeをinterfaceにextendsできる」というのが個人的なハマりポイントでした。

 

おわり

コメント

タイトルとURLをコピーしました