Utility Typesとは
Utility Typesとはコード内で型変換を容易にする為にTypeScriptが提供する(便利な関数のような)型達です。
Partial<T>
Partial<T>はTの全てのプロパティをOptional(任意)のプロパティにしてくれます。
下記のコードPersonでは1つも任意のプロパティが設定されていませんが、Partial<T>を使用する事で、変数taroではfirstNameのみを持つ事ができています。
interface Person {
firstName: string
lastName: string
age: number
}
const taro: Partial<Person> = {
firstName: 'Taro',
}
console.log(taro); //=> { firstName: 'Taro' }
Required<T>
Required<T>はTの全てのプロパティを必須のプロパティにしてくれます。
下記のコードPersonでは全てが任意のプロパティが設定されていますが、Required<T>を使用する事で、変数jiroではfirstNameとlastNameの両方を与えてあげないと、エラーが発生します。
interface Person {
firstName?: string
lastName?: string
}
const jiro: Required<Person> = {
firstName: 'Taro',
}
// Error: property 'lastName' is missing.
Readonly<T>
Readonly<T>はTの全てのプロパティをreadonlyのプロパティにしてくれます。
下記ではReadonly<Todo>としているため、Todoのオブジェクトであるtodoのtitleを更新しようとするとエラーが発生します。
interface Todo {
title: string
}
const todo: Readonly<Todo> = {
title: '家の掃除',
}
todo.title = '夕飯の買い出し' // Cannot assign to 'title' because it is a read-only property.ts(2540)
Record<K, T>
Record<K, T>はKがプロパティとなりT型を持つレコード型を構築します。
言葉ではややわかりずらいので、下記の例を元に考えています。
Record<K, T>のKにはnumberが指定されています。そして、TにはUserが指定されています。
このことから、Record<K.T> を使用して作成されたUserList型はnumber型がプロパティとなり、Userをもつ型となります。
interface User {
name: string
}
type UserList = Record<number, User>
const list: UserList = { 0: { name: 'Taro' }, 1: { name: 'Jiro' } }
console.log(list) //=> { '0': { name: 'Taro' }, '1': { name: 'Jiro' } }
Pick<T,K>
Pick<T,K>は既に存在するT型の中からKで選択した一部のプロパティのみを含んだ新たな型を構築します。
下記の例では、Todoのtitleとcompletedのみを含んだ新たな型TodoPreviewを作成しています。
interface Todo {
title: string
description: string
completed: boolean
}
type TodoPreview = Pick<Todo, 'title' | 'completed'>
const preview: TodoPreview = {
title: '部屋の掃除',
completed: false,
}
console.log(preview) //=> { title: '部屋の掃除', completed: false }
Omit<T,K>
Omit<T,K>は既に存在するT型の中からKで選択した一部のプロパティを除いた新たな型を構築します。
下記の例では、Todoからdescriptionを抜き取って、新たな型TodoPreviewを作成しています。
interface Todo {
title: string
description: string
completed: boolean
}
type TodoPreview = Omit<Todo, 'description'>
const preview: TodoPreview = {
title: '部屋の掃除',
completed: false,
}
console.log(preview) //=> { title: '部屋の掃除', completed: false }
Exclude<T,U>
Exclude はT型のプロパティでU型に代入可能なプロパティを取り除いた型を構築します。
下記の例では、
ExcludedTypeでは"id" | "name"から"id" | "address"に代入可能な"id"を取り除いた型を作成しています。
ExcludedType2ではstringはnumberに代入可能では無いので、stringとなります。
ExcludedType3ではstring | number | booleanで唯一string | booleanに代入可能では無いnumberとなります。
interface TypeA {
id: number
name: string
}
interface TypeB {
id: number
address: string
}
type ExcludedType = Exclude<keyof TypeA, keyof TypeB> // "name"
type ExcludedType2 = Exclude<string, number> // string
type ExcludedType3 = Exclude<string | number | boolean, string | boolean> // number
Extract<T,U>
Extract<T,U>はExclude<T,U>とは反対でT型のプロパティでU型に代入可能なプロパティのみを残した型を構築します。
下記の例では、
ExtractedTypeでは"id" | "name"から"id" | "address"に代入可能な"id"のみ残した型を構築します。
ExtractedType2では代入可能な型は存在しない無いので、neverとなります。
ExtractedType3ではstring | number | booleanでstring | booleanが代入可能なのでstring | booleanとなります。
interface TypeA {
id: number
name: string
}
interface TypeB {
id: number
address: string
}
type ExtractedType = Extract<keyof TypeA, keyof TypeB> // "id"
type ExtractedType2 = Extract<string, number> // never
type ExtractedType3 = Extract<string | number | boolean, string | boolean> // string | boolean
NonNullable<T>
NonNullable<T>はTからnullとundefinedを取り除いた型を構築します。
下記の例では、
TypeAはstring | number | undefinedからundefinedを取り除いた, string | numberになります。
TypeBはstring[] | null | undefinedからnull | undefinedを取り除いた, string[]になります。
type TypeA = NonNullable<string | number | undefined> // string | number
type TypeB = NonNullable<string[] | null | undefined> // string[]
Parameters<T>
Parameters<T>は関数型Tの引数の型をタプル型として抽出した型を構築します。
const func = (text: string, num: number) => {
return `${text}${num}`
}
type TypeA = Parameters<typeof func> // [string, number]
ConstructorParameters<T>
ConstructorParameters<T> はT型のコンストラクタの引数の型をタプルとして抽出した型を構築します。
class Person {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
type TypeA = ConstructorParameters<typeof Person> // [string, number]
ReturnType<T>
ReturnType<T>は関数型Tの戻り値の型を返します。
下記ではfunc2の戻り値の型はnumberなので、TypeAはnumberとなります。
const func2 = (): number => 1
type TypeA = ReturnType<typeof func2> // number
ThisParameterType
関数型Tのthis引数の型を抽出した型を構築します。
--strictFunctionTypesが設定されている時のみ、期待通りの動きをします。詳細はこちら。
function toHex(this: Number) {
return this.toString(16)
}
type TypeA = ThisParameterType<typeof toHex> //Number
OmitThisParameter
関数型Tのthis引数の型を取り除いた型を構築します。
下記の例ではTypeAはtoHexからthis引数を除いた関数型()=> stringを返します。
--strictFunctionTypesが設定されている時のみ、期待通りの動きをします。詳細はこちら。
function toHex(this: Number) {
return this.toString(16)
}
type TypeA = OmitThisParameter<typeof toHex> // () => string
ThisType<T>
ThisType<T>を使用する事で、関数の中で参照されるthisの型をTとてコントロールする事ができます。
-noImplicitThisがが設定されている必要があります。
interface User {
name: string
}
interface Greetings {
hello(): void
}
const user: Greetings & ThisType<User> = {
hello() {
console.log(`${this.name}です。`)
},
}
user.hello()
詳しくはstackoverflowのWhat is TypeScript's ThisType used for?でわかりやすく説明されていました。