Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

概要

前回の続き。

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です。

終わり

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

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

続きは次回。

tfrcm
GemcookでCEO兼エンジニアしてます!
https://gemcook.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away