0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TypeScriptのユーティリティ型を理解する

Last updated at Posted at 2024-12-25

はじめに

今回は、TypeScriptが提供する主要なユーティリティ型について解説します。

ユーティリティ型とは

ユーティリティ型(utility type)は、型から別の型を導き出してくれる型です。functionが実行時の世界の関数だとしたら、ユーティリティ型は型の世界の関数といったイメージです。

参照: サバイバルTypeScript

基本的に、ユーティリティ型<型>という形で使用します。

ユーティリティ型を使いこなせるようになるのは、TypeScript初心者を抜け出すための重要なステップだと思いますので興味のある方はぜひ学習してみてください。

Required / Partial

RequiredPartialは、オブジェクト型を受け取り、それぞれ全てのプロパティを必須にした型と、全てのプロパティを省略可能にした型を返します。

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

type RequiredUser = Required<User>;
// type RequiredUser = {
//     name: string;
//     age: number;
// }

type PartialUser = Partial<RequiredUser>;
// type PartialUser = {
//     name?: string | undefined;
//     age?: number | undefined;
// }

(コメントアウト部はホバーしたときに表示される型です)

元々User型のプロパティは全て省略可能でしたが、Requiredを使うことで全てのプロパティが必須になりました。また、そこに重ねる形でPartialを使うことで全てのプロパティが省略可能になりました。

Readonly

Readonlyは、オブジェクト型を受け取り、全てのプロパティを読み取り専用にした型を返します。

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

type ReadonlyUser = Readonly<User>;

const user: ReadonlyUser = {
  name: 'Taro',
  age: 20,
};
// type ReadonlyUser = {
//    readonly name: string;
//    readonly age: number;
// }

user.name = 'Jiro'; // Error: Cannot assign to 'name' because it is a read-only property.

Readonlyを使うことで全てのプロパティが読み取り専用になりました。
その結果、user.name = 'Jiro';のようにプロパティに値を代入しようとするとエラーが発生してくれるようになります。

注意点として、一定の条件下ではReadonlyを使ってもプロパティの書き換えが可能になることがあるので、注意が必要です。

参考: https://typescript-jp.gitbook.io/deep-dive/type-system/readonly

Record

Recordは、キーの型と値の型を受け取り、その型を持つ全てのプロパティを持つ型を返します。
キーの型はstringnumberなどのプリミティブ型、symbol型とそれらのリテラル型を指定することができます。

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

type UserRecord = Record<string, User>;

const users: UserRecord = {
  '1': { name: 'Taro', age: 20 },
  '2': { name: 'Jiro', age: 30 },
};
// type UserRecord = {
//     [x: string]: User;
// }

type RGB = 'R' | 'G' | 'B';
type Color = Record<RGB, number>;
// type Color = {
//     R: number;
//     G: number;
//     B: number;
// }

const color: Color = {
  R: 255,
  G: 255,
  B: 255,
};

Pick / Omit

PickとOmitは、オブジェクト型を受け取り、それぞれ一部のプロパティを抽出した型と、一部のプロパティを除外した型を返します。
記法はPick<元の型, '抽出するプロパティ名'>Omit<元の型, '除外するプロパティ名'>です。

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

type UserName = Pick<User, 'name'>;
// type UserName = {
//     name: string;
// }

type UserWithoutName = Omit<User, 'name'>;
// type UserWithoutName = {
//     age: number;
// }

// リテラルを使って複数個のプロパティを指定することもできます
type PickNameAndAge = Pick<User, 'name' | 'age'>;
// type pickNameAndAge = {
//     name: string;
//     age: number;
// }

type OmitNameAndAge = Omit<User, 'name' | 'age'>;
// type OmitNameAndAge = {}

Exclude / Extract

ExcludeExtractは、ユニオン型を受け取り、それぞれ一部の型を除外した型と、一部の型を抽出した型を返します。
Pick / Omitのリテラル版と考えると理解しやすいかもしれません。

記法はExclude<元の型, 除外する型>Extract<元の型, 抽出する型>です。

type Cats = '三毛猫' | '黒猫' | '白猫' | '茶トラ' | 'アメショ';

type NotBlackCats = Exclude<Cats, '黒猫'>;
// type NotBlackCats = "三毛猫" | "白猫" | "茶トラ" | "アメショ"

type BlackCats = Extract<Cats, '黒猫'>;
// type BlackCats = "黒猫"

type CatsWithoutBlackAndWhite = Exclude<Cats, '黒猫' | '白猫'>;
// type CatsWithoutBlackAndWhite = "三毛猫" | "茶トラ" | "アメショ"

type CatsOnlyBlackAndWhite = Extract<Cats, '黒猫' | '白猫'>;
// type CatsOnlyBlackAndWhite = "黒猫" | "白猫"

NonNullable

NonNullableは、型を受け取り、その型からnullundefinedを除外した型を返します。

type UserName = string | null | undefined;

type NonNullableUserName = NonNullable<UserName>;
// type NonNullableUserName = string

ReturnType

ReturnTypeは、関数型を受け取り、その関数の戻り値の型を返します。

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

function createUser(name: string, age: number): User {
  return { name, age };
}

type CreateUserReturnType = ReturnType<typeof createUser>;
// type CreateUserReturnType = {
//     name: string;
//     age: number;
// }

Awaited

Awaitedは、Promise型を受け取り、そのPromiseの中身の型を返します。

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

type PromiseUser = Promise<User>;
// type PromiseUser = Promise<User>

type AwaitedPromiseUser = Awaited<PromiseUser>;
// type AwaitedPromiseUser = {
//    name: string;
//    age: number;
// }

AwaitedReturnTypeと組み合わせて使うことが多いです。

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

async function fetchUser(): Promise<User> {
  return { name: 'Taro', age: 20 };
}
// function fetchUser(): Promise<User>

type FetchUserAwaited = Awaited<ReturnType<typeof fetchUser>>;
// type FetchUserAwaited = {
//     name: string;
//     age: number;
// }

InstanceType

InstanceTypeは、コンストラクタ関数型を受け取り、そのコンストラクタ関数のインスタンスの型を返します。

class User {
  name: string;
  age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

type UserInstance = InstanceType<typeof User>;
// type UserInstance = User

Parameters

Parametersは、関数型を受け取り、その関数の引数の型をタプルで返します。

function createUser(name: string, age: number) {
  return { name, age };
}

type CreateUserParameters = Parameters<typeof createUser>;
// type CreateUserParameters = [name: string, age: number]

UpperCase / LowerCase

UpperCaseLowerCaseは、文字列型を受け取り、その文字列を大文字にした型と小文字にした型を返します。

type UppercaseName = Uppercase<'taro'>;
// type UppercaseName = "TARO"

type LowercaseName = Lowercase<'TARO'>;
// type LowercaseName = "taro"

Capitalize / Uncapitalize

CapitalizeUncapitalizeは、文字列型を受け取り、その文字列の最初の文字を大文字にした型と小文字にした型を返します。

type CapitalizedName = Capitalize<'taro'>;
// type CapitalizedName = "Taro"

type UncapitalizedName = Uncapitalize<'Taro'>;
// type UncapitalizedName = "taro"

おわりに

最後まで読んでいただきありがとうございます!

TypeScriptのユーティリティ型は、型を操作するための非常に強力な機能です。
ぜひ、これらのユーティリティ型を使って普段のコーディングを効率化してみてください!

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?