🎃
typeとinterfaceの違いと使い分け
type(型エイリアス)とinterfaceの違いがイマイチわからん
最近TypeScriptを勉強し始めたのですが、typeとinterfaceの違いと使い分け、恩恵がイマイチわからなかったので、調べてまとめてみることにしました。
typeについて
継承が不可能
typeはextendsを用いて継承ができません。
その代わりにintersection(交差型)を使って擬似的に型を継承することは可能です。
type Animal = {
name: string;
};
type Dog = Animal & {
breed: string;
};
const dog: Dog = {
name: "Buddy",
breed: "Golden Retriever",
};
console.log(dog);
// { name: 'Buddy', breed: 'Golden Retriever' }
再宣言ができない
typeは同じ名前の型を再宣言することができません。
type User = {
name: string;
};
type User = {
age: number;
};
このようにUserという型を再宣言しようとするとコンパイルエラーが出ます
index.ts:5:6 - error TS2300: Duplicate identifier 'User'.
5 type User = {
~~~~
interfaceについて
複数宣言できる
同じ名前のinterfaceを複数宣言した場合、プロパティが自動でマージされていきます。
interface User {
name: string;
}
interface User {
age: number;
}
const user: User = {
name: "太郎",
age: 25
};
継承が可能
interfaceはtypeと異なり、型の継承ができます。
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
}
const dog: Dog = {
name: "ポチ",
breed: "柴犬"
};
このようにinterfaceは型の継承ができますが、プロパティをオーバーライドするため、型の互換性がないプロパティについてはエラーが出るので注意が必要です。
interface Animal {
name: string;
}
interface Dog extends Animal {
name: number;
breed: string;
}
const dog: Dog = {
name: "ポチ",
breed: "柴犬",
};
コンパイル結果
index.ts:5:11 - error TS2430: Interface 'Dog' incorrectly extends interface 'Animal'.
Types of property 'name' are incompatible.
Type 'number' is not assignable to type 'string'.
5 interface Dog extends Animal {
~~~
index.ts:11:3 - error TS2322: Type 'string' is not assignable to type 'number'.
プリミティブなユニオンは定義できない
interfaceではプリミティブなユニオンを定義することはできません。
定義できない理由としてはinterfaceがオブジェクトの型を定義するためのものだからですね。(オブジェクトにこのような型は存在しない)
// 定義できない
interface ID = string | number;
もちろんオブジェクトのプロパティをユニオン型にすることはできます。
interface Product {
id: string;
price: number | string; // プリミティブなユニオン型
status: "active" | "draft" | "archived";
tags: string[] | null;
}
まとめ
正直使い分けというよりかはどちらを使うかという派閥のような違いな気がする。。
個人的にはtypeの方が勝手に拡張、および継承がされないのでセキュアなのかなと思ったりしました。
Discussion