読み込み中...

【TypeScript】Partialの使い方を10選の実用コードで解説

TypeScriptのPartialを詳しく解説するイラスト TypeScript
この記事は約24分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

TypeScriptはJavaScriptに静的型付けの強力な能力を追加する言語です。

このため、TypeScriptを用いることで、開発中に様々なエラーを早期発見することが可能となり、品質の高いコードの実装をサポートします。

特に、TypeScriptの型ユーティリティは、柔軟かつ強力な型制御を提供することが特徴です。

その中でも、今回は「Partial」という型ユーティリティに焦点を当てて解説していきます。

Partialは、TypeScriptを使用する際に頻出するユーティリティの一つであり、その特性や使い方を理解することで、さらにTypeScriptの持つ可能性を引き出すことができます。

TypeScriptのPartialを効果的に活用することで、開発効率の向上やエラーの早期発見に寄与することが期待できます。

この記事では、Partialの基本的な概念を超詳細に解説し、初心者でも理解しやすいようにサンプルコードを交えて説明していきます。

さらに、応用例やカスタマイズ方法、注意点なども紹介しますので、TypeScriptのスキルアップを目指す方はぜひ最後までご覧ください。

●TypeScriptのPartialとは

TypeScriptのPartialは、型ユーティリティの一つであり、与えられた型のすべてのプロパティをオプショナルにするユーティリティです。

これにより、オブジェクトの一部のプロパティのみを指定して扱うことができるようになります。

○Partialの基本的な概念

「Partial」の名前の由来は、部分的、あるいは不完全を意味する「partial」という英単語から来ています。

この名前の通り、Partialを使用することで、型の全てのプロパティを持つ必要がなくなり、部分的なオブジェクトの作成や使用が可能となります。

具体的には、ある型の一部のプロパティのみを持つオブジェクトを作成したい、あるいは、オブジェクトの一部のプロパティのみを変更したいという場合に有用です。

●Partialの使い方

TypeScriptでコードを書く際、変数やインターフェース、型にオプショナルな属性を持たせたいときがあります。

そのとき役立つのがPartialという組み込み型です。このセクションでは、Partialの基本的な使用方法をサンプルコードを交えて紹介します。

○サンプルコード1:基本的なPartialの使用方法

まず、基本的なPartialの使い方を理解するためのサンプルコードを見ていきましょう。

// Personというインターフェースを定義します。
interface Person {
    name: string;
    age: number;
    address?: string;
}

// Partialを使って、Personのすべての属性をオプショナルにする新しい型を作成します。
type OptionalPerson = Partial<Person>;

// OptionalPersonの型を持つ変数を作成します。
const person1: OptionalPerson = {
    name: "Taro"
};

const person2: OptionalPerson = {
    name: "Hanako",
    age: 25
};

このコードでは、まずPersonというインターフェースを定義しています。

そして、Partialを使用して、Personのすべての属性(name, age, address)をオプショナルにした新しい型OptionalPersonを作成しています。

その結果、OptionalPerson型の変数では、nameageaddressのいずれか、または全部を省略することができます。

このコードを実行すると、特にエラーは発生せず、person1person2という変数がそれぞれ定義されます。

person1name属性のみを持ち、person2nameage属性を持っています。

○サンプルコード2:オブジェクトとしてのPartial利用

Partial型を使うことで、TypeScriptにおけるオブジェクトの型定義の一部だけを選択的に取り扱うことができます。

これは、例えばオブジェクトの一部のプロパティだけを更新したい場合や、すべてのプロパティを持つオブジェクトを期待する関数に対して、一部のプロパティだけを渡すことが許容されるようにする場面で非常に役立ちます。

ここでは、オブジェクトとしてのPartialの利用方法を具体的なサンプルコードを交えて詳しく解説します。

// まずはUserという型を定義します。
interface User {
    name: string;
    age: number;
    address?: string;
}

// Partial<User>の型を持つオブジェクトを定義する。
const partialUser: Partial<User> = {
    name: "Taro"
};

// User型のデータを更新する関数を定義します。
function updateUser(user: User, newData: Partial<User>): User {
    return { ...user, ...newData };
}

// 上記の関数を使ってUser型のデータを更新する。
const user: User = {
    name: "Taro",
    age: 20
};

const updatedUser = updateUser(user, { address: "Tokyo" });
console.log(updatedUser);

このコードでは、まずUserという型を定義しています。

そして、Partialを使って部分的なUserのデータを持つpartialUserオブジェクトを定義しています。

この時点では、User型のすべてのプロパティを持たなくても問題ありません。

次に、User型のデータを更新する関数updateUserを定義しています。

この関数は、第一引数として完全なUser型のデータ、第二引数としてPartial型のデータを受け取り、二つのデータをマージして新しいUser型のデータを返します。

最後に、updateUser関数を使って、User型のデータuserに住所情報を追加して更新しています。

このコードを実行すると、updatedUserオブジェクトの内容は、nameが”Taro”、ageが20、そしてaddressが”Tokyo”という3つのプロパティを持つオブジェクトとなります。

○サンプルコード3:関数内でのPartial使用例

TypeScriptの特徴的な機能のひとつ、Partialを使用する際に、関数内での活用方法を紹介します。

特に、オブジェクトの一部のプロパティだけを操作したい場面で、Partialは非常に便利です。

type UserInfo = {
    name: string;
    age: number;
    address?: string;
};

function updateUser(data: Partial<UserInfo>) {
    // データの更新処理
}

const user: UserInfo = {
    name: '山田太郎',
    age: 25
};

updateUser({ name: '田中一郎' });

このコードでは、UserInfoという型を定義しています。

このUserInfo型は、ユーザーの情報を表す型で、nameageaddressという3つのプロパティを持っています。

ただし、addressはオプショナルなプロパティとして定義されており、必須ではありません。

関数updateUserは、引数としてPartial<UserInfo>型を取ります。

これにより、この関数にはUserInfoの一部のプロパティだけを持つオブジェクトを渡すことができます。

例えば、updateUser関数を呼び出す際に、名前だけを更新したい場合は、{ name: '田中一郎' }という形でデータを渡すことができます。

このように、関数内でPartialを使用することで、特定のプロパティだけを簡単に操作することが可能になります。

このコードを実行すると、updateUser関数は{ name: '田中一郎' }というデータを受け取り、指定されたプロパティを更新する処理が行われることになります。

○サンプルコード4:条件付き型との組み合わせ

TypeScriptの力強い特徴の1つに「条件付き型」があります。

これは、ある条件が真である場合に型Aを、偽である場合に型Bを返すという強力な型制御の手段です。

この特性をPartialと組み合わせることで、非常に柔軟な型制御が可能となります。

例えば、あるオブジェクトが特定のプロパティを持っている場合にのみ、そのプロパティをPartialにするようなケースを考えてみましょう。

下記のサンプルコードでは、User型がadminプロパティを持っている場合、そのadminプロパティをPartialにする条件付き型を示しています。

type User = {
    id: number;
    name: string;
    admin?: {
        role: string;
        permissions: string[];
    };
};

type MakeAdminPartial<T> = T extends { admin: any } 
    ? { admin?: T['admin'] }
    : T;

type ResultUser = MakeAdminPartial<User>;

このコードでは、MakeAdminPartialという型を定義しています。

この型は、引数として渡された型Tがadminプロパティを持っている場合、そのadminプロパティをPartialに変換します。

持っていない場合は、元の型Tをそのまま返します。

結果として、ResultUser型はadminプロパティがPartialになったUser型と同等になります。

このコードを実行すると、ResultUser型は次のように評価されます。

{
    id: number;
    name: string;
    admin?: {
        role: string;
        permissions: string[];
    };
}

○サンプルコード5:ジェネリクスとの組み合わせ

TypeScriptにおけるジェネリクスは、様々な型に対応するコードを柔軟に書くことができる非常に強力な機能です。

ジェネリクスを利用することで、特定の型を指定せずに関数やクラスを定義できます。

Partialをジェネリクスと組み合わせることで、さまざまな型に対応する関数やクラスを作成する際のプロパティの一部だけを取り扱う、というような柔軟なコードを書くことが可能となります。

具体的なサンプルコードを見ていきましょう。

interface User {
  id: number;
  name: string;
  email: string;
}

function updateUser<T>(id: number, changes: Partial<T>): T {
  // 仮のデータを定義
  const user: User = {
    id: 1,
    name: "山田太郎",
    email: "yamada@example.com"
  };

  // ユーザー情報を更新
  return { ...user, ...changes } as T;
}

const updatedUser = updateUser<User>({ id: 2, email: "new@example.com" });

このコードでは、Userというインターフェースを定義しています。

そして、updateUserという関数はジェネリクスを利用しており、第二引数にPartial型を使用しています。

このようにすることで、User型の一部のプロパティのみを更新することができます。

このコードを実行すると、新しいユーザー情報を持つオブジェクトが生成されます。

今回の例では、idとemailプロパティだけを指定して更新を行なっていますので、updatedUserオブジェクトのidとemailが更新され、nameは元のままとなります。

●Partialの応用例

TypeScriptをより実践的に利用する際、Partialは多岐にわたるシチュエーションでの活用が期待されます。

ここでは、データ更新時の利用例を中心に、Partialをどのように使いこなすかの方法を解説いたします。

○サンプルコード6:データ更新時の利用例

前提として、次のようなユーザー情報を表す型があるとします。

// ユーザー情報の型定義
type User = {
    id: number;
    name: string;
    age: number;
    email: string;
};

このユーザー情報を更新する際、全てのプロパティを変更するわけではなく、特定のプロパティだけを部分的に変更する場面が考えられます。

そのような時にPartialを活用することで、更新する属性だけを指定して型を定義できます。

このコードでは、User型の部分的な属性を持つオブジェクトを受け取り、それを元にユーザー情報を更新する関数を定義しています。

// ユーザー情報の更新関数
function updateUser(data: Partial<User>) {
    // データの更新ロジック(実際にはデータベースや外部APIとの連携を想定)
    console.log("Updated data:", data);
}

// nameとemailだけを更新する例
updateUser({ name: "新しい名前", email: "new.email@example.com" });

このコードを実行すると、updateUser関数は部分的に更新された属性だけを持つオブジェクトを受け取り、それに基づいてユーザー情報を更新します。

今回の例では、nameとemailの2つの属性だけが更新されていることが確認できます。

実際にこのコードを実行した場合、コンソールには「Updated data: { name: “新しい名前”, email: “new.email@example.com” }」と表示されることでしょう。

○サンプルコード7:APIのレスポンス型定義に活用

TypeScriptの型システムは非常に強力であり、それを用いることでさまざまなシチュエーションでの型の安全性を確保することができます。

中でも、APIのレスポンスとして返ってくるデータの型を確定する際にPartialは非常に役立ちます。

通常、APIからのレスポンスには、全ての情報が含まれていることが期待されますが、実際の開発では、場合によっては一部のデータが欠けている場合も考えられます。

このような状況でPartialを利用することで、安全に型を定義することが可能です。

このコードでは、あるユーザー情報を取得するAPIのレスポンスを想定して、その型定義を行っています。

// ユーザーの全情報を表す型
interface User {
    id: number;
    name: string;
    age: number;
    email: string;
}

// APIのレスポンスとして期待される型(部分的な情報のみが含まれる場合がある)
type APIResponse = Partial<User>;

// 実際のAPIからのレスポンス例
const response: APIResponse = {
    id: 1,
    name: '太郎',
    email: 'taro@example.com'
    // ageプロパティが欠けているが、Partialのためエラーとならない
};

このコードでは、Userというユーザーの全情報を表す型を定義しています。

しかし、APIからのレスポンスで全ての情報が必ずしも返ってくるわけではないため、APIResponseという型をPartial<User>として定義しています。

これにより、レスポンスとして受け取るデータにageプロパティが含まれていなくてもエラーとなりません。

このコードを実行すると、response変数には部分的なユーザー情報が格納されます。

このようにして、APIからのレスポンスの型を柔軟に定義できるため、PartialはAPIとの連携を行う際に非常に役立つツールとなります。

○サンプルコード8:Optionalとの違い

TypeScriptでは、オブジェクトの型定義時に特定のプロパティを必須ではなくするためにPartialOptionalという型ユーティリティを用います。

しかし、これら二つのユーティリティには重要な違いがあります。

PartialはTypeScriptの組み込み型であり、オブジェクトのすべてのプロパティをオプショナルにするのに使用します。

これに対して、Optionalは公式に提供される型ではなく、特定のプロパティだけをオプショナルにしたい場合に使用されるカスタム型を指すことが多いです。

まず、Partialを使用したサンプルコードを見てみましょう。

// User型の定義
type User = {
  id: number;
  name: string;
  age: number;
};

// Partial<User>を使用した場合の型定義
type PartialUser = Partial<User>;

// これはエラーにならず、正常に代入できる
const user1: PartialUser = {
  id: 1,
  name: "Taro"
};

このコードでは、User型に3つのプロパティがありますが、Partial<User>を使用すると、すべてのプロパティがオプショナルとなります。

そのため、user1のように一部のプロパティだけを持つオブジェクトも作成できるようになります。

次に、特定のプロパティだけをオプショナルにするカスタムOptional型を作成してみましょう。

// 特定のプロパティだけをオプショナルにするカスタムOptional型
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

// User型のageプロパティだけをオプショナルにする
type UserWithOptionalAge = Optional<User, 'age'>;

// これはエラーにならず、正常に代入できる
const user2: UserWithOptionalAge = {
  id: 2,
  name: "Hanako"
};

このコードでは、Optional型を使用してUser型のageプロパティだけをオプショナルにしました。

このように、特定のプロパティだけをオプショナルにしたい場合にはカスタム型を利用することが推奨されます。

このサンプルコードを実行すると、user1およびuser2はエラーなく代入でき、それぞれのオブジェクトは一部のプロパティが省略された状態で生成されます。

○サンプルコード9:Mapped Typesとの連携

TypeScriptのMapped Typesは非常に強力な機能であり、オブジェクトの各キーに対して型を動的に変更することが可能です。

Partial型との連携を取ることで、より柔軟な型定義が実現できます。

まず、Mapped Typesの基本的な使い方を見てみましょう。

type MyMappedType<T> = {
  [P in keyof T]: T[P] | null;
};

interface User {
  name: string;
  age: number;
}

type NullableUser = MyMappedType<User>;

このコードでは、MyMappedTypeというMapped Typesを定義しています。

これを用いると、指定したオブジェクトの各キーの型をnull許容に変更することができます。

Userインターフェースの各プロパティをnull許容にしたい場合、NullableUserとして新たな型を作成することができます。

では、次にこのMapped TypesとPartialを組み合わせる方法を見ていきましょう。

type PartialAndNullable<T> = {
  [P in keyof T]?: T[P] | null;
};

type PartialNullableUser = PartialAndNullable<User>;

上記のコードは、PartialAndNullableという新しい型を定義しています。

これは、指定したオブジェクトの各キーの型をnull許容にするだけでなく、そのキー自体をオプショナル(存在しなくても良い)にもしています。

つまり、PartialNullableUser型を使うことで、Userインターフェースの各プロパティが存在しない、あるいはnullであることを許容する型を作成できます。

このコードを実行すると、PartialNullableUserは次のようなオブジェクトとして表現できます。

{
  name?: string | null;
  age?: number | null;
}

このように、Mapped TypesとPartialを組み合わせることで、既存の型に対して非常に柔軟なカスタマイズが可能となります。

○サンプルコード10:大規模なプロジェクトでの利用方法

大規模なプロジェクトでは、複数の開発者が関わるため、統一された型定義や一貫したコーディングスタイルが求められます。そんな中で、Partial型は特定の場面で非常に役立つツールとなります。

ここでは、大規模なプロジェクトでのPartialの活用例を、具体的なコードと共に解説します。

コードを確認してみましょう。

interface User {
    id: number;
    name: string;
    age: number;
    email: string;
}

function updateUser(id: number, changes: Partial<User>): void {
    // 仮のデータベース更新関数
    databaseUpdateFunction(id, changes);
}

// 実行例
const updatedInfo = {
    name: "新しい名前",
    email: "new_email@example.com"
}

updateUser(1, updatedInfo);

このコードでは、Userというインターフェースを定義しています。

そして、updateUserという関数を用意して、ユーザー情報を部分的に更新することができるようにしています。

updateUser関数の第二引数には、Partial型を使用しています。

これにより、Userインターフェースのすべてのプロパティを持つオブジェクトではなく、一部のプロパティだけを持つオブジェクトを受け取ることができるようになっています。

実行例として、updatedInfoオブジェクトでnameemailだけを更新する場面を考えました。

これがPartialの威力です。必要なプロパティのみを指定して更新処理を行うことが可能です。

このコードを実行すると、IDが1のユーザーのnameemailupdatedInfoの内容に基づいて更新されます。

●注意点と対処法

○Optionalとの違いに注意

TypeScriptには、Partialの他にもOptionalという型も存在します。

しかし、これら二つの型は似ているようで異なる点がいくつかあります。

初心者の方々にとっては混同しやすい部分もあるため、しっかりと違いを理解しておきましょう。

interface OptionalUser {
    id?: number;
    name?: string;
    age?: number;
    email?: string;
}

このように、Optionalではプロパティの後に?を付けることで、そのプロパティが存在しなくても良い、という型を定義できます。

しかし、Partialとは違い、この場合、各プロパティはundefinedも許容する形となります。

つまり、Partialを使う場合はプロパティが存在するか否かのみを定義するのに対し、Optionalを使う場合はプロパティの存在に加えて、undefinedという値も許容するようになります。

大規模なプロジェクトではこの違いが重要になる場面もあるため、注意が必要です。

○型安全を確保する方法

TypeScriptの大きな魅力の一つは、型安全を提供してくれる点です。

しかし、PartialやOptionalなどの柔軟な型を使うことで、逆に型安全が失われるリスクも増えます。

このようなリスクを避けるための対策方法をいくつか紹介します。

  1. 必要最低限の場所でのみ、PartialやOptionalを使用する。
  2. 更新や操作を行う前に、オブジェクトのプロパティの存在チェックを行う。
  3. 関数やメソッド内で、型アサーションを使用して、明示的に型を指定する。

下記のコードは、オブジェクトのプロパティの存在チェックの一例です。

function printUser(user: Partial<User>): void {
    if (user.name && user.email) {
        console.log(`名前: ${user.name}, メール: ${user.email}`);
    } else {
        console.log('ユーザー情報が不足しています。');
    }
}

●カスタマイズ方法

TypeScriptは、JavaScriptに静的型チェックを追加するための言語です。

そのため、TypeScriptの中核的な機能の一つとして、豊富な型ユーティリティが提供されています。

これらの型ユーティリティは、コードの保守性を高め、より堅牢なプログラムを書くための鍵となります。

特に、Partialは非常に役立つ型ユーティリティの一つですが、TypeScriptの型システムを最大限に活用するためには、Partialだけでなく、他の型ユーティリティとの組み合わせも考慮することが大切です。

ここでは、Partial以外の型ユーティリティとの組み合わせについて、サンプルコードとともに解説していきます。

○Partial以外の型ユーティリティとの組み合わせ

TypeScriptには、Partial以外にも多くの型ユーティリティが存在します。

例えば、ReadonlyPickOmitなどがあります。

これらの型ユーティリティとPartialを組み合わせることで、更に高度な型操作を行うことができます。

□ReadonlyとPartialの組み合わせ

このコードでは、ReadonlyPartialを組み合わせて、部分的に更新できるが、その他のプロパティは読み取り専用となる型を定義しています。

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

type UpdatableUser = Readonly<Partial<User>>;

const user: UpdatableUser = {
  name: "Taro"
};

// user.age = 25;  // これはエラーとなる

このコードを実行すると、userオブジェクトはnameプロパティのみを持つことができ、それを変更することはできません。

しかし、ageプロパティを追加しようとするとエラーとなります。

□PickとPartialの組み合わせ

Pick型ユーティリティは、特定のプロパティだけを取り出すことができます。

下記のコードでは、PickPartialを組み合わせて、User型からnameプロパティのみを部分的に取得し、それを更新できる型を作成しています。

type UserName = Pick<User, 'name'>;

type UpdatableUserName = Partial<UserName>;

const userName: UpdatableUserName = {
  name: "Taro"
};

このコードを実行すると、userNameオブジェクトはnameプロパティのみを持ち、それを自由に更新することができます。

□OmitとPartialの組み合わせ

Omitは、特定のプロパティを除外した型を作成する型ユーティリティです。

下記のコードでは、User型からageプロパティを除外し、残りのプロパティを部分的に取得して更新できる型を定義しています。

type WithoutAge = Omit<User, 'age'>;

type UpdatableWithoutAge = Partial<WithoutAge>;

const userWithoutAge: UpdatableWithoutAge = {
  name: "Taro"
};

このコードを実行すると、userWithoutAgeオブジェクトはnameプロパティのみを持ち、それを自由に更新することができます。

しかし、ageプロパティを持つことはできません。

まとめ

TypeScriptでのPartialの取り扱いは、初心者から上級者まで幅広く利用されているものです。

本記事を通じて、Partialの基本的な概念から、その多彩な使い方、さらにはカスタマイズの方法について解説してきました。

Partialのような便利な型ユーティリティは今後も増えていくことでしょう。

常に最新の情報をキャッチアップし、自身のスキルを磨き続けることで、より質の高いコードを書くことができるようになるでしょう。

今回学んだ知識を活用し、TypeScriptのプロジェクトでのコーディングを更に効率的かつ堅牢にしてください。