TypeScript:インターフェイスvsタイプ


回答:


574

TypeScript言語仕様に従って:

常に名前付きオブジェクトタイプを導入するインターフェイス宣言とは異なり、タイプエイリアス宣言は、プリミティブ、ユニオン、およびインターセクションタイプを含むあらゆる種類のタイプの名前を導入できます。

仕様はさらに言及し続けます:

インターフェイスタイプには、オブジェクトタイプリテラルのタイプエイリアスと多くの類似点がありますが、インターフェイスタイプはより多くの機能を提供するため、タイプエイリアスよりも一般的に推奨されます。たとえば、インターフェースタイプ

interface Point {
    x: number;
    y: number;
}

タイプエイリアスとして書くことができます

type Point = {
    x: number;
    y: number;
};

ただし、これを行うと、次の機能が失われます。

  • インターフェイスはextendsまたはimplements句で名前を付けることができますが、オブジェクトタイプリテラルのタイプエイリアスは TS 2.7以降はtrueになりません。
  • インターフェイスは複数の宣言をマージできますが、オブジェクトタイプリテラルのタイプエイリアスはできません。

109
2番目の違いの「複数のマージされた宣言」とはどういう意味ですか?
jrahhali 2017年

66
@jrahhaliインターフェースを2回定義すると、typescriptはそれらを1つにマージします。
Andrey Fedorov 2017

39
@jrahhaliタイプを2回定義すると、typescriptによってエラーが発生します
Andrey Fedorov

18
@jrahhaliinterface Point { x: number; } interface Point { y: number; }
Nahuel Greco

20
最初の点extends or implementsはもう当てはまらないと思います。タイプは、によって拡張および実装できますclasstypescriptlang.org/play/…
dark_ruby

776

2019アップデート


現在の回答と公式ドキュメントは古くなっています。TypeScriptの初心者にとって、使用されている用語は例がなければ明確になりません。以下は、最新の違いのリストです。

1.オブジェクト/関数

どちらも、オブジェクトまたは関数のシグネチャの形状を記述するために使用できます。ただし、構文は異なります。

インターフェース

interface Point {
  x: number;
  y: number;
}

interface SetPoint {
  (x: number, y: number): void;
}

タイプエイリアス

type Point = {
  x: number;
  y: number;
};

type SetPoint = (x: number, y: number) => void;

2.その他のタイプ

インターフェイスとは異なり、型エイリアスは、プリミティブ、共用体、タプルなどの他の型にも使用できます。

// primitive
type Name = string;

// object
type PartialPointX = { x: number; };
type PartialPointY = { y: number; };

// union
type PartialPoint = PartialPointX | PartialPointY;

// tuple
type Data = [number, string];

3.延長

どちらも拡張できますが、構文は異なります。さらに、インターフェイスとタイプエイリアスは相互に排他的ではないことに注意してください。インターフェイスは型エイリアスを拡張でき、その逆も可能です。

インターフェースはインターフェースを拡張します

interface PartialPointX { x: number; }
interface Point extends PartialPointX { y: number; }

型エイリアスは型エイリアスを拡張します

type PartialPointX = { x: number; };
type Point = PartialPointX & { y: number; };

インターフェイスは型エイリアスを拡張します

type PartialPointX = { x: number; };
interface Point extends PartialPointX { y: number; }

型エイリアスがインターフェースを拡張

interface PartialPointX { x: number; }
type Point = PartialPointX & { y: number; };

4.実装

クラスは、インターフェースまたは型エイリアスを、まったく同じ方法で実装できます。ただし、クラスとインターフェースは静的なブループリントと見なされます。したがって、ユニオン型を指定する型エイリアスを実装/拡張することはできません。

interface Point {
  x: number;
  y: number;
}

class SomePoint implements Point {
  x = 1;
  y = 2;
}

type Point2 = {
  x: number;
  y: number;
};

class SomePoint2 implements Point2 {
  x = 1;
  y = 2;
}

type PartialPoint = { x: number; } | { y: number; };

// FIXME: can not implement a union type
class SomePartialPoint implements PartialPoint {
  x = 1;
  y = 2;
}

5.宣言のマージ

型エイリアスとは異なり、インターフェイスは複数回定義でき、単一のインターフェイスとして扱われます(すべての宣言のメンバーがマージされます)。

// These two declarations become:
// interface Point { x: number; y: number; }
interface Point { x: number; }
interface Point { y: number; }

const point: Point = { x: 1, y: 2 };

9
公式ドキュメントが古い場合、提供した情報はどこで確認できますか?
iX3

59
この投稿に基づいて、型エイリアスではなくインターフェイスを選択する唯一の理由は、インターフェイスの宣言マージ(ポイント5)機能を使用する場合にあると思われます。それを超えて、それらは同等です(そして、型エイリアスはより簡潔な構文を提供すると私は主張します)。
maxedison

17
私は常にオブジェクト型リテラルのインターフェイスを使用していますが、それ以外の場合は型を使用する方が理にかなっています。また、宣言のマージはとにかく使用すべきではないと思います。実際、プロジェクトの別のファイルでインターフェイスが宣言されているとは思わない余分なプロパティ、型チェックは元々、この忍者のようなインターフェースで難しくないように人生を楽にするために行われました:D
Ahmed Kamal

8
それで、基本的に、私たちが本当に快適に使用できると思うものに対する「ほぼ個人的な」選択です。1つの理由は別として、あなたは単に使うことができますtypeinterface?どちらを使用するべきか、まだ混乱しています。
ジョセフブリッグズ

7
インターフェースのマージが必要な理由を誰かに教えてくださいませんか?それは私を混乱させる可能性があるようです。インターフェースの定義をさまざまなブロックに分散したいのはなぜですか?
Vanquish46

95

TypeScript 3.2(2018年11月)以降、次のことが当てはまります。

ここに画像の説明を入力してください


9
あなたが提供したテーブル/画像がどのように生成されたかについての詳細を教えていただけませんか 例:ソースコードまたはドキュメントへのリンク
iX3

23
はい、私はコンテンツのソースではなく、プレゼンテーションを意味しました。
iX3

3
クラスがタイプまたはインターフェースのいずれかを拡張できるとは思わない。なぜそうしたいのか本当にわからない。
Dan King

7
テキストの画像を投稿するのではなく、実際のテキストを直接投稿に含めます。テキストの画像は簡単に解析したり検索したりすることができず、視覚障害のあるユーザーはアクセスできません。
アンドリューマーシャル

2
このテーブルには、その内容をサポートするためのソースがありません。私はそれに依存しません。たとえば、type特定の制限付きでを使用して再帰型を定義できます(TypeScript 3.7以降では、これらの制限もなくなりました)。インターフェイスは型を拡張できます。クラスは型を実装できます。さらに、データをテーブルのスクリーンショットとして表示すると、視覚障害のある人はデータに完全にアクセスできなくなります。
のMichałMiszczyszyn


5

タイプの例:

//オブジェクトのツリー構造を作成します。交差(&)がないため、インターフェースで同じことを行うことはできません

type Tree<T> = T & { parent: Tree<T> };

//変数を制限して、いくつかの値のみを割り当てるように入力します。インターフェイスにユニオン(|)がありません

type Choise = "A" | "B" | "C";

//型のおかげで、条件付きメカニズムのおかげでNonNullable型を宣言できます。

type NonNullable<T> = T extends null | undefined ? never : T;

インターフェースの例:

// OOPのインターフェイスを使用し、「実装」を使用してオブジェクト/クラスのスケルトンを定義できます

interface IUser {
    user: string;
    password: string;
    login: (user: string, password: string) => boolean;
}

class User implements IUser {
    user = "user1"
    password = "password1"

    login(user: string, password: string) {
        return (user == user && password == password)
    }
}

//他のインターフェースでインターフェースを拡張できます

    interface IMyObject {
        label: string,
    }

    interface IMyObjectWithSize extends IMyObject{
        size?: number
    }


-2

ドキュメントは説明しました

  • 1つの違いは、インターフェースはどこでも使用される新しい名前を作成することです。タイプエイリアスは新しい名前を作成しません。たとえば、エラーメッセージはエイリアス名を使用しません。古いバージョンのTypeScriptでは、タイプエイリアスは拡張または実装できませんでした(他のタイプを拡張/実装することもできません)。バージョン2.7以降、新しい交差タイプを作成することでタイプエイリアスを拡張できます
  • 一方、インターフェースで形状を表現できず、共用体またはタプル型を使用する必要がある場合は、通常、型エイリアスが適しています。

インターフェースとタイプエイリアス

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.