TypeScriptのinterface:構文からinterfaceとtypeの違いまで
TypeScriptのinterface
TypeScript interface:構文、extends、マージ、typeとの違い | We.Inc
interfaceをフィールドごとに作成して対応するtypeエイリアスを確認し、省略可能なメンバーとreadonlyメンバー、extends、宣言のマージ、typeエイリアスのほうが適した場面を学べます。
interfaceはオブジェクトの形に名前を付けます。どのプロパティを持ち、それぞれがどの型かを表します。?でプロパティを省略可能に、readonlyで変更不可にし、extendsで別の形を土台にでき、同じ名前を再び宣言するとメンバーがマージされます。interfaceはコンパイル後のJavaScriptには何も残らず、型チェッカーを導くだけです。
interfaceの構文の一覧
- 省略可能なプロパティ
- nickname?: string;
- 再代入できないプロパティ
- readonly id: number;
- メソッド
- greet(other: User): string;
- 任意の数の文字列キー
- [key: string]: number;
- 別の形を再利用する
- interface Admin extends User { ... }
- 複数の形を組み合わせる
- interface A extends B, C { ... }
下のビルダーでフィールドを追加し、省略可能やreadonlyにチェックを入れて、interfaceまたは同等のtypeエイリアスをコピーしましょう。その下のセクションでは、拡張、マージ、そしてinterfaceとtypeの選択が本当に重要になる数少ないケースを解説します。
- interfaceに名前を付け、別のinterfaceを土台にする場合は、extendsの欄にその名前を入力します。
- プロパティごとに行を追加し、型と、省略可能かreadonlyかを選びます。
- 同じ行からビルダーが書き出すinterfaceとtypeエイリアスを確認します。
- どちらかのバージョンをコードにコピーします。
- オブジェクトの形にはまずinterfaceを使い、ユニオン型、タプル、mapped typeが必要なときにtypeを使いましょう。これはTypeScriptハンドブック自体が勧めている目安です。
- readonlyが防ぐのは、そのプロパティ1つへの再代入だけです。その中に入れ子になったオブジェクトは変更でき、実行時には何も強制されません。
- 省略可能なプロパティは、その型またはundefinedとして読み取られるので、使う前に確認するか、分割代入でデフォルト値を与えましょう。
- interface名はInvoiceやCartItemのように、単数形でわかりやすくしましょう。IInvoiceのような接頭辞は、エディターがすでに教えてくれること以上の情報を加えません。
よくある質問
interfaceとtypeのどちらを使うべきですか?
オブジェクトの形にはどちらも使え、ハンドブックはほぼ好みの問題だとし、typeにしかない機能が必要になるまではinterfaceを勧めています。ユニオン型、タプル、プリミティブ、mapped typeやconditional typeにはtypeを、宣言のマージが必要なときはinterfaceを使いましょう。
宣言のマージとは何ですか?
すでに存在する名前でinterfaceを宣言すると、エラーにならずにメンバーが追加されます。ライブラリはこの仕組みを利用して、型を拡張できるようにしています。たとえばWindowにプロパティを追加する場合です。typeエイリアスで同じ名前を繰り返すとエラーになります。
マージされた2つのinterfaceで、プロパティの型が異なるとどうなりますか?
コンパイラーがエラーを報告します。2つの型のインターセクションの場合、宣言の時点では衝突が報告されず、プロパティがneverになります。問題が後から表面化するので、原因をたどるのが難しくなります。
interfaceで関数や配列を表せますか?
はい。(value: string): booleanのような呼び出しシグネチャは関数を、[index: number]: stringのようなインデックスシグネチャは配列のようなオブジェクトを表します。単純なケースでは、type Check = (v: string) => booleanのようなtypeエイリアスのほうが読みやすくなります。
interfaceは実行時に存在しますか?
いいえ。コンパイル後には何も残らないので、interfaceにinstanceofを使ったり、そのキーを列挙したりはできません。実行時のガードで値を確認し、その戻り値の型をinterfaceで注釈しましょう。
extendsとインターセクションの違い
- interface Bear extends AnimalはAnimalのすべてのメンバーをコピーし、さらにメンバーを追加できます。typeエイリアスでは、インターセクションで同じことをします:type Bear = Animal & { honey: boolean }。
- ハンドブックによると、extendsのほうがコンパイラーにとって高速になりうるうえ、衝突するメンバーを宣言した場所ですぐに報告します。インターセクションは、自分が管理していない形をつなぎ合わせるのに便利です。
省略可能、readonly、インデックスシグネチャ
- 名前の後に疑問符を付けるとプロパティは省略可能になり、読み取り時の型にundefinedが含まれます。readonlyは作成後のそのプロパティへの代入を防ぎますが、コンパイル時のチェックにすぎません。
- [key: string]: numberのようなインデックスシグネチャは、キーを事前に列挙できない辞書を表します。同じinterface内の名前付きプロパティは、インデックスシグネチャの値の型に合っていなければなりません。
マージでグローバルやライブラリの型を拡張する
- interfaceはマージされるので、宣言ファイルから組み込みの形に独自のフィールドを追加できます。よくあるのは、スクリプトが設定するプロパティをWindowに追加し、キャストなしで型チェックを通せるようにするケースです。
interfaceとtypeエイリアスの比較
それぞれの宣言でできること
- 名前を再宣言してメンバーを追加する
- できる(マージ)
- できない、識別子の重複エラー
- mapped typeとconditional type
- できない
- できる
よく書くパターン
1つまたは複数のinterfaceを拡張する
AdminはUserのすべてのメンバーに加えて独自のメンバーを持ち、Cardは関係のない2つの形を組み合わせます。
Windowでの宣言のマージ
.d.tsファイルに置くと、window.appVersionがどこでも型チェックを通るようになります。
インデックスシグネチャと呼び出しシグネチャ
Scoresは任意の文字列キーを受け付け、Validatorは呼び出し可能な値を表します。
interfaceビルダー
interface名
extends(省略可)
プロパティ{n}の名前
プロパティ{n}の型
省略可能
readonly
プロパティ{n}を削除
プロパティを追加
interfaceとして
typeエイリアスとして
interfaceをコピー
typeをコピー
名前は英字、$、_のいずれかで始め、英字、数字、$、_だけを使ってください。
無料で始める · クレジットカード不要
関連: ガイド|Webマーケティングと集客を学ぶ
製品
ご利用いただける方
機能
リソース
会社情報
サイトマップを見る