はじめに
型定義では主にTypeとInterfaceが使われますが、どっちを使うのがいいのか、2つの違いについて調べたので書いていきます。
参考
サバイバルTypeScriptを参考にしたので、よければこちらもご覧ください。
サバイバルTypeScript
2つの違いについて
まずは2つの違いについて書いていきます。
Type(型エイリアス)
・継承不可(ただし、&を使えば似たようなことができる)
・継承による上書きができる。
・同名の型定義はできない。
・MappedTypesが使えない。
Interface
・継承可能
・継承による上書きができない。
・同名の型が定義できる。
・MappedTypesが使えない。
継承について
Interfaceは以下のように、型エイリアスを継承できる。
interface Animal {
name: string;
}
type Creature = {
dna: string;
};
interface Dog extends Animal, Creature {
dogType: string;
}
しかし、Typeは継承ができないが、その代わりに&を使えば、似たようなものはできる。
type Animal = {
name: string;
};
type Creature = {
dna: string;
};
type Dog = Animal &
Creature & {
dogType: string;
};
継承による上書きについて
継承時のパラメータの上書きは、Interfaceはできますが、Typeはできないです。
Interfaceの継承
interface Animal {
name: any;
price: {
yen: number;
};
legCount: number;
}
interface Dog extends Animal {
name: string;
price: {
yen: number;
dollar: number;
};
}
// 最終的なDogの定義
// nameの型とpriceの中身が書き換えられ、dollerも追加されています。
interface Dog {
name: string;
price: {
yen: number;
dollar: number;
};
legCount: number;
}
Typeの継承
type Animal = {
name: number;
price: {
yen: number;
dollar: number;
};
};
type Dog = Animal & {
name: string;
price: {
yen: number;
euro: number;
};
};
// 最終的なDogの定義
type Dog = {
name: never; // 同じ名前のパラメータを定義すると、never型になる。エラーにはならない。
price: {
yen: number;
dollar: number;
euro: number;
};
};
同名の型定義について
Interfaceは定義できますが、Typeはできません。
Interfaceは定義できますが、指定した型が違うとエラーになってしまいます.
エラーの理由は、最初はsameNameSameTypeIsAllowedの型をnumberに指定したのに、次に再定義したときはstring型で定義しているためです。
interface SameNameInterfaceIsAllowed {
myField: string;
sameNameSameTypeIsAllowed: number;
sameNameDifferentTypeIsNotAllowed: string;
}
interface SameNameInterfaceIsAllowed {
newField: string;
sameNameSameTypeIsAllowed: number;
}
interface SameNameInterfaceIsAllowed {
sameNameDifferentTypeIsNotAllowed: number;
// エラー↓
Subsequent property declarations must have the same type. Property
'sameNameDifferentTypeIsNotAllowed' must be of type 'string', but here has type 'number'.
}
Typeは同名のものを定義した時点でエラーになります。
type SameNameTypeWillError = {
// エラー↓
Duplicate identifier 'SameNameTypeWillError'.
message: string;
};
type SameNameTypeWillError = {
// エラー↓
Duplicate identifier 'SameNameTypeWillError'.
MappedTypesについて
これについての説明は省きます。以下のページで詳しく説明されています。
https://typescriptbook.jp/reference/type-reuse/mapped-types
使い分けについて
これについては明確な正解はないそうです、、、
それぞれのメリット、デメリットを理解した上で
プロジェクトや所属するチームのルールに則るしかないようです。
個人的には、Typeのほうが安全かなと思っています。
理由としては、同名の定義ができないので、誤って同じ名前で宣言をしてしまってもエラーが出るので、バグに繋がることを防げるからです。
最後に
他にも記事を書いているので、良ければ見ていってください。
基本設計について
Vue.jsとNode.jsでチャットアプリを作った
Next.js×TypeScriptでTODOアプリを作成する