TypeScript インターフェースと型のどちらかを選ぶとき、多くの開発者は困惑します。
TypeScript 言語の隠れた魅力を発見しながら、賢明なプラクティスとデフォルトを探り、「インターフェイスと型のどちらを使用すべきか」という質問に答えましょう。 プリミティブ、ユニオン型、タプル型などの新しい型を作成するようなユースケースでは、type
キーワードを使用するのが好ましいと思います。 それ以外のもの (オブジェクトや配列) では、interface
です。
interface
はデータ構造を扱うときに非常に便利で、非常に視覚的に表現できます (type
もそうですが、これは通常私の好むところです)。 オブジェクトや配列に type
を選択することはまったく問題ありません。
とはいえ、TypeScript における型とインターフェイスについて、より多くの情報に基づいた判断ができるように、もう少し掘り下げてみましょう。 型とインターフェイス
一般に、私たちは意図する変数や関数の引数に対して型をモデル化するためにデータ構造を定義します。
Lets create an object as an interface (recommended approach):
interface Milkshake { name: string; price: number; getIngredients(): string;}
ここで、私は、それがデータを割り当てられた変数ではなくインターフェースであることが明らかなので、インターフェースを使うことを好みます – 素晴らしい読みやすさが得られるでしょう。 name
と price
を使ってレコードを設定し、getIngredients
をメソッド呼び出しに使っています。
🎉 無料でダウンロードできます
ForEach を超える準備はできていますか? Reduce、Find、Filter、Every、Some、Mapなどの高度なメソッドに自信を持ちましょう。
- JavaScript のデータ構造をイミュータブルな操作で管理する方法を完全に理解する
- 31 ページにわたる深い構文、実際の例、ヒントとトリック
- 3 時間でよりきれいでより良い構造のプログラミング ロジックを書く
これを型と比較すると、=
:
type Milkshake = { name: string; price: number; getIngredients(): string;};
これは、ここでtype
を使うよりもinterface
を選んだ私のちょっとした好みですが、あなたが望むなら、自由にtype
キーワードを使ってかまいませんよ。
Intersecting (交差)。 型 vs インターフェイス
交差は、単に 1 つまたは複数の型を組み合わせることを意味します! このパターンは、interface
または type
の両方を使用して実現できます。
次のインターフェイスを想定して、interface
と type
をどのように交差させるかを説明します:
interface MilkshakeProps { name: string; price: number;}interface MilkshakeMethods { getIngredients(): string;}
インターフェイスでは、extends
キーワードを使用して交差させるでしょう。 複数のインターフェイスを使用して、他の場所で定義されたすべてのプロパティとメソッドを含む最終的な Milkshake
インターフェイスに拡張(継承)する方法を紹介します:
// { name: string, price: number, getIngredients(): string }interface Milkshake extends MilkshakeProps, MilkshakeMethods {}
これで Milkshake
はどこでも使用でき、name
、price
、getIngredients
を 1 つのインターフェイス参照で使用できる利点が得られました。
type
を使用して、&
を介して型を交差させる方法を次に示します:
// { name: string, price: number, getIngredients(): string }type Milkshake = MilkshakeProps & MilkshakeMethods;
型を交差させたい場合は、interface
の代わりに type
を使用することをお勧めします。 extends
を使用すると、少し冗長で読みにくい感じがしますが、これは type
キーワードのために作られたものだと思います。
Interface も制限されています。type
のエイリアスは、タプル、プリミティブ、ユニオンなど、より複雑な型に使用することが可能です。 型 vs インターフェイス
プリミティブ型について説明します。 そう、文字列、数値などです。 プリミティブ型は type
エイリアスにのみ割り当てることができます:
type MilkshakeName = string;interface Milkshake { name: MilkshakeName; price: number;}
もしプリミティブを使う必要がある場合は、type
を使ってください。 インターフェイスは構文がサポートしてないので、単なる1つの値の場合はここではNGです。
🎉ダウンロードは無料です。
ForEach を超える準備はできていますか? Reduce、Find、Filter、Every、Some、Mapなどの高度なメソッドに自信を持ちましょう。
- JavaScript のデータ構造をイミュータブルな操作で管理する方法を完全に理解する
- 31 ページにわたる深い構文、実際の例、ヒントとトリック
- 3 時間でよりクリーンで優れた構造化プログラミングロジックを書く
コードを複雑にしすぎないように!
Class: 型 vs インターフェイス
あなたが type
または interface
を選択したかどうかにかかわらず、クラスでの使用方法は同じです:
type Size = { size: string};interface Milkshake { name: string; price: number; getIngredients(): string;}class Order implements Size, Milkshake { // Size size = 'large'; // Milkshake name = 'Vanilla'; price = 399; getIngredients() { return ; }}
クラスは実装/拡張ユニオン型をサポートしません、なぜならそれらは静的ブループリントとみなされるからです。 これは、TypeScript の制限により、今すぐには動的には変更できないため、実装する各型について非常に明確にする必要があることを意味します。
Learn more about TypeScript Interfaces vs Classes!
Functions: 型とインターフェイス
通常、私は、ほとんどの場合、匿名関数を入力したいので、type
エイリアスを使用して関数を作成します。
interface IngredientsFn { () => string;}
type
を使用した場合と比較して、少し不自然に感じますが、どちらも完全に有効な TypeScript であり、コードがコンパイルされるときに違いは生じません。
When not to use a Type
さて、さまざまな比較と推奨されるアプローチを検討しましたが、次は Declaration Merging について説明します。これは TypeScript の機能ですが、interface
だけに適用され、type
ではなく interface
を選択する理由となるものです。
type
を使用して型をマージするには、次のように新しい最終的な type
:
type MilkshakeProps = { name: string; price: number;};type MilkshakeMethods = { getIngredients(): string;};type Milkshake = MilkshakeProps & MilkshakeMethods;
type Milkshake
は MilkshakeProps
と MilkshakeMethods
の型のエイリアスとなる。 この動作を実現するために、Milkshake
を作成する必要があり、3 つの個別の型エイリアスを与えることに注意してください。
インターフェースでは、実際には宣言のマージという、よりスマートなアプローチ(少し賢すぎると言う人もいるかもしれません)があります。
同じスコープで同じ interface
を 2 回宣言することにより、宣言のマージを実現できます (これは、別のモジュールからインターフェイスをインポートするか、別のインターフェイスの隣にローカルに宣言するかのいずれかです):
// declared once...interface Milkshake { name: string; price: number;}// declared again the same, it works!interface Milkshake { getIngredients(): string;}// { name: string, price: number, getIngredients(): string }const milkshake: Milkshake = { name: 'Banana', price: 399, getIngredients() {...}};
Milkshake には現在 name
, price
そして getIngredients
があります! しかし、宣言のマージは良いことなのでしょうか? 私は正直言って好きではありませんし、益というより害につながる可能性があると感じています。 私なら、宣言のマージを使用するよりも、type
を使用して型を構成します。 TypeScript における型とインターフェースの主な違い。
個人的な好みもありますが、要約すると、私はオブジェクトには interface
を使用し、type
エイリアス キーワードを使って新しい型をその場で構成します。 これらの新しい型は、インタフェースや、タプル、ユニオン、交差型などの他の型である可能性もあります。
ほとんどの場合、インターフェイスと型は、ここで説明したいくつかの相違点を除いて、ほとんど同じです。 もしあなたがTypeScriptのスキルについて真剣に考えているなら、次のステップは私のTypeScriptコースを見ることです。これらは、言語の基本を完全に詳しく教えるだけでなく、日々のTypeScript開発で必要となる多くの高度な使用例を教えます!
Happy coding!