🔲

TypeScriptの高度な型

2023/10/30に公開

はじめに

前回TypeScriptの基本的な型についてまとめましたが、今回は高度な型についてまとめてみました。

https://zenn.dev/collabostyle/articles/701e3a1b42d97d

型ガード

変数や値の型をチェックして、特定の型に制約を設けるための仕組みです。
コード内で型安全性を向上させ、型エラーを回避できます。

typeofを使用した型ガード

function logValue(value: string | number) {
  if (typeof value === "string") {
    console.log(value.toUpperCase());
  } else {
    console.log(value.toFixed(2));
  }
}

instanceofを使用したクラス型の型ガード

class Car {
  start() {
    console.log("Car started");
  }
}

class Bike {
  start() {
    console.log("Bike started");
  }
}

function startVehicle(vehicle: Car | Bike) {
  if (vehicle instanceof Car) {
    vehicle.start();
  } else {
    vehicle.start();
  }
}

in演算子を使用したプロパティの型ガード

interface Bird {
  fly(): void;
}

interface Fish {
  swim(): void;
}

function move(animal: Bird | Fish) {
  if ("fly" in animal) {
    animal.fly();
  } else {
    animal.swim();
  }
}

交差型

複数の型を結合して新しい型を作成できます。

type Person = {
  name: string;
  age: number;
};

type Employee = {
  employeeID: number;
  position: string;
};

// 交差型を使用して、Person型とEmployee型を結合
type PersonAndEmployee = Person & Employee;

const john: PersonAndEmployee = {
  name: "John Doe",
  age: 30,
  employeeID: 12345,
  position: "Software Engineer",
};

ジェネリクス型

関数やクラス、インターフェースの型定義をパラメータ化できる仕組みです。
ジェネリクスを活用することで、型安全性を維持しながら、さまざまなデータ型に対応する再利用可能なコードを書くことができます。

ジェネリクス関数

function identity<T>(arg: T): T {
  return arg;
}

const result1: string = identity<string>("Hello World");
const result2: number = identity<number>(42);

ジェネリクスクラス

class Container<T> {
  private value: T;

  constructor(value: T) {
    this.value = value;
  }
}

const container1: Container<string> = new Container<string>("Hello World");
const container2: Container<number> = new Container<number>(42);

ジェネリクスインターフェース

interface Pair<T, U> {
  first: T;
  second: U;
}

const pair1: Pair<number, string> = { first: 1, second: "two" };
const pair2: Pair<string, boolean> = { first: "one", second: true };

型エイリアス

既存の型に別名を付けることができる仕組みです。
これにより、複雑な型を簡潔な名前で参照できます。

基本的な型エイリアス

type Person = {
  name: string;
  age: number;
};

const alice: Person = {
  name: "Alice",
  age: 30,
};

ジェネリクス型エイリアス

type Pair<T, U> = {
  first: T;
  second: U;
};

const nameAndAge: Pair<string, number> = {
  first: "Alice",
  second: 30,
};

Union型と型エイリアス

type Result = "success" | "error";

const success: Result = "success";
const error: Result = "error";

関数型エイリアス

type Calculation = (a: number, b: number) => number;

const add: Calculation = (a, b) => a + b;
const subtract: Calculation = (a, b) => a - b;

インデックス型

オブジェクトのプロパティ名に対して特定の型を割り当てるための便利な方法です。

// インデックス型の定義
interface Dictionary {
  [key: string]: number; // string型のキーに対してnumber型の値を関連付ける
}

// オブジェクトの作成
const myDictionary: Dictionary = {
  "apple": 10,
  "banana": 5,
  "cherry": 8,
};

// インデックス型を使ったアクセス
console.log(myDictionary["apple"]); // 10

// インデックス型を使った新しいプロパティの追加
myDictionary["grape"] = 15;
console.log(myDictionary["grape"]); // 15

// インデックス型を使ったプロパティの削除
delete myDictionary["cherry"];
console.log(myDictionary); // { "apple": 10, "banana": 5, "grape": 15 }
コラボスタイル Developers

Discussion