
目次
- ユーティリティ型(Utility Types)とは
- ユーティリティ型は全部で22個
- 1. Awaited<Type>
- 2. Capitalize<StringType>
- 3. ConstructorParameters<Type>
- 4. Exclude<UnionType, ExcludedMembers>
- 5. Extract<Type, Union>
- 6. InstanceType<Type>
- 7. Lowercase<StringType>
- 8. NoInfer<Type>
- 9. NonNullable<Type>
- 10. Omit<Type, Keys>
- 11. OmitThisParameter<Type>
- 12. Parameters<Type>
- 13. Partial<Type>
- 14. Pick<Type, Keys>
- 15. Readonly<Type>
- 16. Record<Keys, Type>
- 17. Required<Type>
- 18. ReturnType<Type>
- 19. ThisParameterType<Type>
- 20. ThisType<Type>
- 21. Uncapitalize<StringType>
- 22. Uppercase<StringType>
ユーティリティ型(Utility Types)とは
ユーティリティ型(Utility Types)とは一般的な型変換を容易にするための型です。
例えば、TypeScriptで任意のプロパティをピックアップしたオブジェクト型を作成したい場合は以下のようなコードになります。
type MyPick<T, K extends keyof T> = {
[P in K]: T[P]
}
type Person = {
name: string
age: number
address: string
}
type PersonNameAndAge = MyPick<Person, 'name' | 'age'>
const person: PersonNameAndAge = {
name: 'John',
age: 30
}
console.log(person)
TypeScriptでは、このようなよく使用される型はユーティリティ型として用意されているため、前述のコードの場合は型を自作しなくてもPick<T, Keys>で実装できます。
type Person = {
name: string
age: number
address: string
}
type PersonNameAndAge = Pick<Person, 'name' | 'age'>
const person: PersonNameAndAge = {
name: 'John',
age: 30
}
console.log(person)
ユーティリティ型は全部で22個
現在のユーティリティ型は全部で22個あります。(2024年7月現在)
TypeScriptの参考書やサバイバルTypeScriptなどのWebサイトだと、9個くらいしか書かれていないので、初心者だとユーティリティ型は全部で9個くらいだと思っている方もいます。
ユーティリティ型をすべて知らないと、TypeScriptの型定義を有効に活用できません。
この記事ではTypeScriptのユーティリティ型の全22個の使い方についてコード付きで解説します。
※ 記事内のユーティリティ型の見出しはアルファベット順で記載
1. Awaited<Type>
非同期関数のawaitやPromisesの.then()メソッドのような操作、特にPromisesを再帰的にアンラップする方法をモデル化します。
type Product = {
id: number
title: string
// 以下略
}
type ProductType = Awaited<ReturnType<typeof getProduct>>
async function getProduct(id: number): Promise<Product> {
const response = await fetch(`https://dummyjson.com/products/${id}`)
// 中略
}
(async () => {
const product: ProductType = await getProduct(1)
document.getElementById('result')!.textContent = product.title
})()
※ ちなみにPromise<Type>はユーティリティ型ではない。
詳細は別記事をご参照ください。
2. Capitalize<StringType>
型の文字列の最初の文字を大文字に変換します。
type Greeting = 'hello world!'
type CapitalizeGreeting = Capitalize<Greeting>
const hello: CapitalizeGreeting = 'Hello world!'
console.log(hello)
3. ConstructorParameters<Type>
クラスのコンストラクタ引数の型を取得します。
class Person {
constructor(public name: string, public age: number) {}
}
type PersonConstructorParameters = ConstructorParameters<typeof Person>
// type PersonConstructorParameters = [name: string, age: number]
const person: PersonConstructorParameters = ['John', 34]
console.log(person)
4. Exclude<UnionType, ExcludedMembers>
任意の型を除外します。
type Fruit = 'apple' | 'orange' | 'grape' | 'mikan'
type Citrus = Exclude<Fruit, 'apple' | 'grape'>
// type Citrus = "orange" | "mikan"
5. Extract<Type, Union>
任意の型を抽出します。
type Fruit = 'apple' | 'orange' | 'grape' | 'mikan'
type NotCitrus = Extract<Fruit, 'apple' | 'grape'>
// type NotCitrus = "apple" | "grape"
6. InstanceType<Type>
与えられたclass型からそのインスタンスの型を取得します。
オブジェクトの型に使う場合は有用だが、new Personで変数に入れる場合は型推論が効くので、あまり意味がない。
class Person {
constructor(public name: string, public age: number) {}
greet() {
console.log(`My name is ${this.name}`)
}
}
type PersonInstance = InstanceType<typeof Person>
const person: PersonInstance = {
name: 'John',
age: 34,
greet() {
console.log(`Hello, ${this.name}!`)
},
}
person.greet()
7. Lowercase<StringType>
型の文字列の各文字を小文字に変換します。
type Greeting = 'HELLO WORLD!'
type CapitalGreeting = Lowercase<Greeting>
const hello: CapitalGreeting = 'hello world!'
console.log(hello)
8. NoInfer<Type>
型推論を防止します。
function findIndexInArray<T extends string>(
elements: T[],
item: NoInfer<T>
): string {
return elements.find((el) => el === item)
}
type FoodType = 'apple' | 'banana' | 'cookie';
const foods: FoodType[] = ['apple', 'banana', 'cookie']
findIndexInArray(foods, 'apple')
findIndexInArray(foods, 'grape')
// Argument of type '"grape"' is not assignable to parameter of type 'FoodType'.
9. NonNullable<Type>
nullとundefinedを除外して型を返します。
type MyType = string | number | null | undefined
type NonNullMyType = NonNullable<MyType>
// string | number
10. Omit<Type, Keys>
型から指定したプロパティを除外します。
type Person = {
name: string
age: number
address: string
}
type PersonWithoutAge = Omit<Person, 'age'>
// type PersonWithoutAge = {
// name: string;
// address: string;
// }
11. OmitThisParameter<Type>
関数型からthis引数を取り除いた新しい関数型を作成します。
type Example = {
method(this: { name: string }, arg: string): void
}
type ExampleWithoutThis = OmitThisParameter<Example['method']>
// type ExampleWithoutThis = (arg: string) => void
12. Parameters<Type>
関数型からその引数の型を抽出してタプル型として取得します。
function add(a: number, b: number): string {
return `Answer is ${a + b}!`
}
type AddParam = Parameters<typeof add>
// type AddParam = [a: number, b: number]
13. Partial<Type>
元の型のすべてのプロパティをオプショナルにした新しい型を作成します。
type Person = {
name: string;
age: number;
address: string;
}
type PartialPerson = Partial<Person>
// type PartialPerson = {
// name?: string;
// age?: number;
// address?: string;
// }
14. Pick<Type, Keys>
元の型から指定したキーを取り出して、新しい型を作成します。
type Person = {
name: string
age: number
address: string
}
type NameAndAge = Pick<Person, 'name' | 'age'>
// type NameAndAge = {
// name: string;
// age: number;
// }
15. Readonly<Type>
元の型のすべてのプロパティを読み取り専用にした新しい型を作成します。
type Person = {
name: string
age: number
address: string
}
type ReadonlyPerson = Readonly<Person>
// type ReadonlyPerson = {
// readonly name: string;
// readonly age: number;
// readonly address: string;
// }
16. Record<Keys, Type>
指定されたキーに対して、指定された型の値を持つオブジェクトを作成します。
type ExampleRecord = Record<'foo' | 'bar' | 'baz', string>
// type ExampleRecord = {
// foo: string;
// bar: string;
// baz: string;
// }
以下のように組み合わせることもできます。
type Role = 'admin' | 'user'
type RolePermissions = {
canEdit: boolean
canView: boolean
}
type RoleRecord = Record<Role, RolePermissions>
const rolePermissions: RoleRecord = {
admin: {
canEdit: true,
canView: true,
},
user: {
canEdit: false,
canView: true,
}
}
console.log(rolePermissions)
17. Required<Type>
元の型のすべてのプロパティを必須にした新しい型を作成します。
type Person = {
name: string
age?: number
address?: string
}
type RequiredPerson = Required<Person>
// type RequiredPerson = {
// name: string;
// age: number;
// address: string;
// }
18. ReturnType<Type>
関数型の引数として渡された場合に、その関数の返り値の型を取得します。
function getUser() {
return {
id: 1,
name: 'John',
}
}
type User = ReturnType<typeof getUser>
// type User = {
// id: number;
// name: string;
// }
19. ThisParameterType<Type>
関数型の型引数として指定された関数のthisパラメーターの型を取得します。
const user = {
name: 'John',
greet(this: { name: string }) {
console.log(`Hello, ${this.name}`)
},
}
type ThisType = ThisParameterType<typeof user.greet>
// type ThisType = {
// name: string;
// }
20. ThisType<Type>
クラスやオブジェクトのメソッドのthis型を指定します。
const user = {
name: 'John',
greet(this: { name: string }) {
console.log(`Hello, ${this.name}`)
},
}
type This = ThisType<typeof user.greet>
// type This = ThisType<(this: {
// name: string;
// }) => void>
const user = {
name: 'John',
greet(this: { name: string }) {
console.log(`Hello, ${this.name}`)
},
}
type This = ThisType<typeof user.greet>
// type This = ThisType<(this: {
// name: string;
// }) => void>
21. Uncapitalize<StringType>
型の文字列の最初の文字を小文字に変換します。
type Greeting = 'Hello World!'
type UncapitalizeGreeting = Uncapitalize<Greeting>
const hello: UncapitalizeGreeting = 'hello World!'
console.log(hello)
22. Uppercase<StringType>
型の文字列の各文字を大文字に変換します。
type Greeting = 'hello world!'
type UppercaseGreeting = Uppercase<Greeting>
const hello: UppercaseGreeting = 'HELLO WORLD!'
console.log(hello)