【TypeScript入門】クラスの型定義(インターフェースと型エイリアスの違い)

クラスの型定義について復習

前回に記事ではTypeScriptにおける、関数とクラスの基本的な型の定義方法と、クラスの継承・合成についてみていきました。

【TypeScript入門】クラスの型定義(インターフェースと型エイリアスの違い)

この記事の中で、クラスは型定義を目的とした抽象クラスと、実装部分の2通りに分かれると伝えました。


今回はこの部分を詳しく見ていきましょう。

インターフェース

抽象クラスには現状でabstract修飾子を使った方法と、インターフェースを使った方法があります。
abstract修飾子を使った方法は抽象クラスでありながら、実装部分を含む事ができる為、保守性を考えて現状ではあまり使われていません。

今回はインターフェースのみを説明していきます。

//インターフェースにてShapreを定義interface Shape {  readonly name: string;  getArea: () => number;}//インターフェースにてQuadrangleを定義interface Quadrangle {  side: number;}//Rectabgleクラスには抽象クラスのShapreとQuadrangleの型を使う!!class Rectangle implements Shape, Quadrangle {  readonly name = 'rectangle';  side: number;  sideB: number;  constructor(side: number, sideB: number) { this.side = side; this.sideB = sideB;  }  getArea = (): number => this.side * this.sideB;}const rect = new Rectangle(6, 5);console.log(rect.getArea());

この様に

interface Quadrangle {  side: number;}

で定義できて、

class Rectangle implements Quadrangle { }

で使う事ができる!!詳しい使い方などはこちらの記事が参考になります。

Typescriptのinterfaceの使い方

型エイリアス

任意の型に別名を与えて再利用できるものを「型エイリアス」と呼びます。
定義の仕方はインターフェース同様です。

type Enemy = {  hp: number  mp: number}

インターフェースと型エイリアスの違い

基本的に、現在ではインタフェースよりも型エイリアスの方ができる事が多いです。
その上で型エイリアスの方が柔軟性と保守性が高い為、モダンな環境では型エイリアスの方が好まれています。

それぞれの違いについてみていきましょう。

型エイリアスは任意の型を定義できる

type Unit = 'USD' | 'EUR' | 'JPY' | 'GBP';

などの様にリテラル型なども使えます。インターフェースではオブジェクトとクラスのみしか参照できません。

インターフェースは既存の方を名前を変えずに拡張できてしまいます。

interface User { age: number; }interface User { species: 'rabbit' | 'bear' | 'fox' | 'dog';}

型エイリアスはユニオン型とインターセクションで複雑な型表現ができる

 

ユニオン型

ユニオン型が『A または B』と適用範囲を増やしていく型の表現方法です。

type A = {  foo: number;  bar?: string;};type B = { foo: string };type C = { bar: string };type D = { baz: boolean };typeAorB=A|B; //ユニオン型AまたはB{foo:number|string;bar?:string} typeAorC=A|C; //ユニオン型AまたはC{{foo:number;bar?:string}or{bar:string} typeAorD=A|D; //ユニオン型AまたはD{{foo:number;bar?:string}or{baz:boolean}

インターセクション型

インターセクション型は『A かつ B』と複数の型をひとつに結合させる事ができます。
→オブジェクト型の合成が可能になります。

type A = { foo: number };type B = { bar: string };type C = {  foo?: number;  baz: boolean;};typeAnB=A&B; //インターセクション型AかつB{foo:number,bar:string} typeAnC=A&C; //インターセクション型AかつC{foo:number,baz:boolean} 

ユニオン型とインターセクション型を組み合わせることで、複雑な型表現も可能です。

type A = { foo: number };type B = { bar: string };type C = {  foo?: number;  baz: boolean;};typeCnAorB=C&(A|B); // Cかつ(AまたはB)//{ foo: number, baz: boolean } or { foo?: number, bar: string, baz: boolean }

型の Null 安全性を保証する

TypeScript はデフォルトの設定ではすべての型に null と undefined を代入できてしまいます。


このままだと静的型付け言語の特徴でもあるnull安全性を担保できません。

対策として、コンパイラオプション strictNullChecks を設定する必要があります。

りあクト! TypeScriptで始めるつらくないReact開発 第3版【Ⅰ. 言語・環境編】

tsconfig.json ファイルに対して次の様に記述してください。

"strictNullChecks": true,

もしnullを許容したい場合はこの様に書けばOKです。

let foo: string | null = 'fuu';

 

まとめ

今回はクラスの型定義の方法となる

・インターフェース
・型エイリアス

についてをメインに解説していきました。

現状では、型エイリアスの方が機能として優れていると説明しましたが、現場レベルではまだまだインターフェースが使われている場合もある為、今回はインターフェースの解説も混ぜました。

もし、新しくコードを書く際があれば、型エイリアスでの書き方をお勧めします。

また、今回の記事で、TypeScriptの基本的な型は全て解説しました。
ここまでの内容を抑えていれば、TypeScriptのコードを読む際にもわかる事が増えていると思います。

 

次回以降は応用編として、より高度な型表現を解説していきます。
以上です。

TypeScriptの入門記事一覧

【TypeScript入門】JavaScriptとの違いや特徴を詳しく解説
【TypeScript入門】基本的な型の定義方法
【TypeScript入門】関数とクラスの型定義(継承と合成)
【TypeScript入門】クラスの型定義(インターフェースと型エイリアスの違い)
【TypeScript】高度な型表現について
【TypeScript】型ガードと型アサーションでunknown型を使い勝手良くする