LoginSignup
36
8

More than 5 years have passed since last update.

TypeScript1.8 入門③ (インタフェース)

Last updated at Posted at 2016-07-03

概要

前回の続き。

TypeScriptの機能

インタフェース

インタフェースは色々な場面で利用されます。
主に2つの役割があります。

1. オブジェクトの型に名前を付ける。
2. クラスの中でメンバの実装を約束させる。

インタフェースはざっくりゆうと、宣言を約束させる為の機能です。

①の例としては

sample.ts
let getTotal = (result: {a: number, b: number}): number => {
  return result.a + result.b;
};

let result = {
  a: 43,
  b: 84
};

console.log(getTotal(result));

上の様なコードがあった場合、getTotal関数の引数であるresultがオブジェクトであるとします。
引数のresultオブジェクトの中身の型を指定する場合は、上記の様に少し冗長になってしまいます。

そこで登場するのがインタフェースです。

sample.ts

interface Result {
  a: number;
  b: number;
}

let getTotal = (result: Result): number => {
  return result.a + result.b;
};

let result = {
  a: 43,
  b: 84
};

console.log(getTotal(result));

インタフェースを定義し、予めオブジェクトの型を定義する事で、オブジェクトの型に名前を付ける事が可能になります。
getTotalの引数部分が非常にすっきりしましたね。

構造的部分型

少し難しい概念にはなるのですが、TypeScriptではある型のプロパティさえ持っていればその型とみなすという考え方です。
今回であれば、resultオブジェクトにcというプロパティを持っていても、Result型とみなしてくれます。
そのおかげで、新しいResult型(cプロパティを持ったResult型)を定義しなくても、そのままResult型を柔軟に使い回す事が可能です。

逆を言えば、インタフェースで定義されている型を持っていないとエラーになります。

継承

クラスと同じ様にインタフェースも継承が可能です。
クラスの継承と違う点は、クラスは1つのクラスからしか継承できませんが、インタフェースは複数のインタフェースから継承可能です。

sample.ts

interface SpringResult {
  spring: number;
}
interface FallResult {
  fall: number;
}
interface FinalResult extends SpringResult, FallResult {
  final?: number;
}

let getTotal = (result: FinalResult): number => {
  if (result.final) {
    return result.spring + result.fall + result.final;
  }
  return result.a + result.b;
};

let result = {
  spring: 38,
  fall: 95,
  final: 45
};

console.log(getTotal(result));

extendsキーワード

extendsキーワードを使えば、インタフェースを継承していく事が可能です。
インタフェースの継承は複数可能です。

オプション可能

インタフェースのプロパティに[?]を付ける事で、オプションプロパティにする事が可能です。
前回の関数宣言でも出てきましたね。

これを利用する事で、柔軟に設計する事が可能になります。

getTotalで処理の分岐を入れる必要はあります。

最終的には、SpringResultとFallResultを継承したFinalResultがgetTotalのオブジェクト引数の型になっています。

インタフェースとクラスの組み合わせ

インタフェースとクラスを組み合わせる事で、インタフェースの実装を約束したクラスを作成する事が可能です。
例えば、

sample.ts

interface GameUser {
  score: number;
  showScore(): void;
}

class User implements GameUser {
  score: number = 0;
  constructor(protected _name: string) {
  }
  sayHi(): void {
    console.log(`Hi! i am ${this._name}`);
  }
  showScore(): void {
    console.log(`score: ${this.score}`);
  }
}

上のコードで言えば、GameUserのプロパティの実装を約束した、Userクラスを作成する事ができます。

implementsキーワード

インタフェースからインタフェースを継承する際は、extendsキーワードを利用しましたが、クラスからインタフェースを継承する際はimplementsキーワードを利用します。
implementsキーワードを使えば、複数のインタフェースをクラスに継承させる事が可能になります。

また実装自体は、クラス内部で行う為、インタフェース内ではシグネチャを記載するだけでOKです。

終わり

インタフェースを使えば、大規模開発の設計もしっかりできるのではないかと思います。
インタフェースをしっかり定義し、インタフェースの継承を約束したクラスを作成したり、オブジェクトの型として引数の必須性を約束したり様々な場面で活躍するのではないでしょうか。

次回は、「ジェネリクス」について、解説したいと思います。

続きは次回。

36
8
0

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
36
8