項目13 type(型エイリアス)とinterfaceの違いを知る
TypeScriptで名前付きの型を定義したい場合、2パターン存在する
type(型エイリアス)
interface
一般的に、interfaceが使える場所では使い、typeでなければならない場合(ユニオン型など)や、typeを使ったほうがスッキリする場合(関数型)はtypeを使う
類似点
余剰プロパティチェック
インデックスシグネチャ
関数型の定義
関数型を表現するのに自然な書き方
code:ts
type TFn = (x: number) => string;
const toStrT: TFn = x => '' + x; // OK
関数が呼び出し可能なオブジェクトであることを表現する場合
code:ts
interface IFn {(x: number): string;}
type TFnAlt = {(x: number): string;};
const toStrI: IFn = x => '' + x; // OK
const toStrTAlt: TFnAlt = x => '' + x; // OK
ジェネリックのサポート
型の拡張
⚠️interfaceが拡張できるtypeは、interfeceとしても定義可能なオブジェクト型のみ
ユニオン型はinterfeceでは拡張できない
相違点
ユニオンのtypeはあるがinterfeceはない
code:ts
type Input = { /* ... */ };
type Output = { /* ... */ };
// 下記はinterfeceでは実現できない
type NamedVariable = (Input | Output) & { name: string };
interfaceとextendsによる拡張はtypeと&による拡張より、少し多くエラーチェックを行う
code:ts
interface Person {name: string; age: string;}
type TPerson = Person & { age: number; }; // エラーにならないが、この型は使えない
interface IPerson extends Person { age: number:} // 型エラー
interfaceとextendsによる拡張のほうがより厳密
オーグメンテーション
同じ名称のinterfaceは宣言のマージが行われる
主に、型宣言ファイルで使われる
code:ts
interface IState {name: string; capital: string;}
interface IState {population: number;}
const wyoming: IState = {name: 'Wyoming', capital: 'Cheyenne', population: 578_000}; // OK
interfeceは名前で参照するが、typeはその定義に置き換えてしまう場合がある点
code:ts
export function getHummer() {
type Hummingbird = { name: string; weightGrams: number; };
const ruby: Hummingbird = { name: 'Ruby-throated', weightGrams: 3.4 };
return ruby;
};
const rubyThroat = getHummer();
// ^? const rubyThroat: Hummingbird
上記のコードから.d.tsファイルを作成すると、関数本体は不要なため、型エイリアスをインライン化する
code:ts
export declare function getHummer(): {name: string; weightGrams: number;};
型システムは構造的であるため、どの値がこの型に代入可能かには影響しない。
ただ、型情報の表示には影響し、.d.tsファイルにも影響を及ぼす
このインライン化はコンパイラーのパフォーマンスに悪影響を及ぼすことがある
くわしくは項目78 コンパイラーのパフォーマンスに注意を払う
interfaceの場合は、エラーになる
code:ts
export function getHummer() {
// ~~~~~~~~~
// Return type of exported function has or is using private name 'Hummingbird'.
// エクスポートされた関数の戻り値の型が、プライベート名 'Hummingbird' を持っているか、
// 使用しています。
interface Hummingbird { name: string; weightGrams: number; };
const bee: Hummingbird = { name: 'Bee Hummingbird', weightGrams: 2.3 };
return bee;
};
使い分け
複雑な型を表現したい場合はtype
単純なオブジェクトは、interfece
ただプロジェクトの方針に従うべき
基本的にはinterfeceを使うで良さそう
#TypeScript