型エイリアスとinterfaceについて

Posted: 2020/8/2
TypeScript/
基本の型

TypeScript での基礎的な型を理解していただいた上で、今回は型エイリアスと、Interface について説明していきたいと思います。

型エイリアス

変数に名前をつけて、値を代入できるのと同様に、TypeScript では型に名前をつけて宣言することができます。これを型エイリアス(type alias)と呼びます。宣言方法は、type 型名とします。

以下に例を示します。

type Coffee = {
  name: string;
  country: string;
  code: number;
};

新たに定義した、Coffee を利用するには、以下のようにします。

// アラビカコーヒーを定義
const arabica: Coffee = {
  name: "Arabica",
  country: "Ethiopia",
  code: 1,
};

// Coffeeで定義されていたcodeプロパティが存在しないためエラー
const american: Coffee = {
  name: "American coffee",
  country: "America",
};

新たにコーヒーの種類として、型エイリアスを利用してアラビカコーヒーを定義しています。下の例では Coffee の型エイリアスで指定していた code プロパティが欠如しているためエラーとなります。

また、JavaScript の変数と同様に、基本同じ型を 2 度宣言することはできません。さらに、型エイリアスはブロックスコープなため、スコープの有効範囲はブロック内に限ります。そのため、以下のように別のブロックでは同じ型を宣言することができます。

type status = "done";
type status = "progress";
// コンパイルエラー : 2度同じ名前の型エイリアスを宣言できない

if (isStatus) {
  type status = "done";
} else {
  type status = "progress";
}
// 型エイリアスはブロックスコープなので2度同じ名前の型エイリアスを宣言したことにならない

新たにコーヒーの種類として、型エイリアスを利用してアラビカコーヒーを定義しています。下の例では Coffee の型エイリアスで指定していた code プロパティが欠如しているためエラーとなります。

また、JavaScript の変数と同様に、基本同じ型を 2 度宣言することはできません。さらに、型エイリアスはブロックスコープなため、スコープの有効範囲はブロック内に限ります。そのため、以下のように別のブロックでは同じ型を宣言することができます。

type status = "done";
type status = "progress";
// コンパイルエラー : 2度同じ名前の型エイリアスを宣言できない

if (isStatus) {
  type status = "done";
} else {
  type status = "progress";
}
// 型エイリアスはブロックスコープなので2度同じ名前の型エイリアスを宣言したことにならない

interface

interface も、型エイリアスと同様に型に名前をつけることができます。型エイリアスとは微妙な違いがいくつかあるので、まずは宣言方法からみていきましょう。以下のようにinterfaceは宣言できます。

interface Person {
  name: string;
  sex: string;
  age: number;
}

型エイリアスだと以下のように表現できます。

type Person = {
  name: string;
  sex: string;
  age: number;
};

interfaceを拡張するには、extendsを用います。以下の例では、Person インタフェースを拡張した Engineer インタフェースを宣言し、利用しています。

// Personを拡張してEngineerインタフェースを定義
interface Engineer extends Person {
  language: string;
}

// Personで宣言したプロパティに加えて拡張されたlanguageプロパティが使える
const Tom: Engineer = {
  name: "Tom",
  sex: "male",
  age: 20,
  language: "TypeScript",
};

同じようなことを型エイリアスでしてみます。

type Engineer = Person & {
  language: string;
};

型エイリアスと interface の違い

ここまでは interface と型エイリアスにほぼ違いがないと感じると思いますので、それらの細かな違いを説明していきます。

型エイリアスは右辺に任意の型を指定できる

先ほど interface と型エイリアスとで型を拡張する例を説明しましたが、型エイリアスは型を拡張するさいに右辺に|&のような型演算子を指定することができます。しかし interface は指定できないため、型エイリアスの方が汎用的であると言えます。

interface は拡張時に割り当て可能かチェックを行う

interface を拡張する場合に、拡張元の interface に割り当てることができるかチェックを行います。

interface Person {
  name: string;
  sex: string;
}

interface Person2 extends Person {
  name: number;
}
// コンパイルエラー
// プロパティ"name"にstringが拡張元で割り当てられているため、numberを割り当てることはできない

型エイリアスの場合は型を結合してコンパイル時のエラーを出さないようにします。

type Person = {
  name: string;
};
type Person2 = Person & {
  name: number;
};
// Person2の型はオーバーロードされる

同一スコープ内に同一名のインタフェースが存在すると自動でマージされる

以下のように、同一名のインタフェースが存在すると自動でマージされます。

interface Person {
  name: string;
  sex: string;
  age: number;
}
// この段階で自動マージされる
interface Person {
  country: string;
}

const john: Person = {
  name: "John",
  sex: "male",
  age: 30,
  country: "Canada",
};

一方で同じ名前の型エイリアスを宣言するとコンパイルエラーが生じてしまいます。

type Person = {
  name: string;
};
type Person = {
  sex: string;
};
// コンパイルエラー

以上、型エイリアスと interface についてでした!

どちらも TypeScript を扱う上では頻繁に使用するので、是非理解し、使えるようになってくださいね 💪

ではまた 🙌

https://qiita.com/tkrkt/items/d01b96363e58a7df830e