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できる」というのが個人的なハマりポイントでした。

 

おわり

HTML/CSS/JavaScript
スポンサーリンク
この記事を書いた人
penpen

1991生まれ。
2019年くらいからフロントエンドエンジニアを目指している元アフィリエイターです💩

penpenをフォローする
penpenをフォローする
penpenメモ

コメント

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