TypeScriptの型エイリアス、インターセクション型、discriminated unionを使いこなす
TypeScriptにおける「declare class」と「interface」の違い
共通点
- プロパティやメソッドを定義できる
- オブジェクトの型を定義できる
相違点
項目 | declare class | interface |
---|---|---|
使用目的 | 既存のクラスを参照 | オブジェクト型の定義 |
継承 | 可能 | 可能 |
実装 | implements キーワードでクラスが実装 | クラスで直接使用 |
修飾子 | public, private, protected | なし |
メソッド | シグネチャのみ | シグネチャと実装 |
使用例 | 外部ライブラリの型定義 | 自作のオブジェクト型定義 |
使用目的
- interface
自作のオブジェクト型を定義する場合に使用する。 - declare class
外部ライブラリなどで既に定義されているクラスを参照する場合に使用する。
継承
- interface
他の interface を継承できる。 - declare class
他の declare class や interface を継承できる。
実装
- interface
クラスで直接使用できる。 - declare class
implements キーワードを使ってクラスが実装する。
修飾子
- interface
修飾子を使用できない。 - declare class
public, private, protected などの修飾子を使用できる。
メソッド
- interface
メソッドのシグネチャと実装を定義できる。 - declare class
メソッドのシグネチャのみ定義できる。
使用例
- interface
自作の API やコンポーネントの型定義に使用される。 - declare class
jQuery や React などの外部ライブラリの型定義に使用される。
使い分け
- メソッドの実装が不要な場合は
interface
を使用する。 - メソッドの実装が必要な場合は
declare class
を使用する。 - 自作のオブジェクト型を定義する場合は
interface
を使用する。 - 既存のクラスを参照する場合は
declare class
を使用する。
外部ライブラリの型定義 (declare class)
// jQuery の型定義
declare class jQuery {
// ...
}
// jQuery を使用
const $ = new jQuery();
自作のオブジェクト型定義 (interface)
// ユーザー情報
interface User {
name: string;
age: number;
}
// ユーザー情報の作成
const user: User = {
name: "John Doe",
age: 30,
};
メソッドの実装 (declare class)
// 挨拶をするクラス
declare class Greeter {
// 挨拶する
greet(): string;
}
// Greeter クラスを実装する
class MyGreeter implements Greeter {
greet(): string {
return "Hello, world!";
}
}
// MyGreeter クラスを使用
const greeter = new MyGreeter();
const greeting = greeter.greet();
console.log(greeting); // "Hello, world!"
メソッドの実装 (interface)
// 動物
interface Animal {
// 鳴き声を上げる
makeSound(): string;
}
// 犬
class Dog implements Animal {
makeSound(): string {
return "ワンワン";
}
}
// 猫
class Cat implements Animal {
makeSound(): string {
return "ニャーニャー";
}
}
// 動物の鳴き声を表示
function printSound(animal: Animal) {
console.log(animal.makeSound());
}
// Dog と Cat の鳴き声を表示
printSound(new Dog()); // ワンワン
printSound(new Cat()); // ニャーニャー
- より複雑な型定義には、ジェネリック型やエイリアス型など、他の機能も活用できます。
型エイリアス
// ユーザー情報
type User = {
name: string;
age: number;
};
// ユーザー情報の作成
const user: User = {
name: "John Doe",
age: 30,
};
インターセクション型
// ユーザー情報
interface User {
name: string;
}
// 住所情報
interface Address {
street: string;
city: string;
}
// ユーザー情報と住所情報の型
type UserWithAddress = User & Address;
// ユーザー情報と住所情報の作成
const userWithAddress: UserWithAddress = {
name: "John Doe",
age: 30,
street: "123 Main Street",
city: "New York, NY",
};
discriminated union
// 種類
type Kind = "A" | "B";
// オブジェクト
interface Object {
kind: Kind;
}
// A 型のオブジェクト
interface AObject extends Object {
value: string;
}
// B 型のオブジェクト
interface BObject extends Object {
number: number;
}
// オブジェクトの型
type Object = AObject | BObject;
// オブジェクトの作成
const object: Object = {
kind: "A",
value: "Hello, world!",
};
// オブジェクトの種類を取得
const kind = object.kind;
// オブジェクトの種類によって処理を分岐
switch (kind) {
case "A":
const aObject = object as AObject;
console.log(aObject.value);
break;
case "B":
const bObject = object as BObject;
console.log(bObject.number);
break;
}
- discriminated union は、オブジェクトの種類によって処理を分岐したい場合に使用する。
- インターセクション型は、複数のインターフェースを組み合わせて型を定義したい場合に使用する。
- 型エイリアスは、インターフェースよりも簡潔な記法で型を定義したい場合に使用する。
- シンプルなオブジェクト型には
interface
を使用する。
typescript