【TypeScript】ユーティリティ型を整理してみる
どうもフロントエンドエンジニアのoreoです。
今回は、ユーティリティ型について整理してみたいと思います。いつも同じようなユーティリティ型を使っていますが調べてみるとたくさんありますね。
1 ユーティリティ型とは?
TypeScriptで用意されている型変換が簡単にできる型です。ユーティリティ型では、前回の記事で紹介したGenerics型が利用されています。型をよしなに変換してくれる便利ツールのようなイメージです!
2 ユーティリティ型
公式ドキュメントに記載されているユーティリティ型を整理していきます。
2-1 Partial<Type>
Partial<Type>
は、type
の全てのプロパティをオプショナルにします。
type CustomerData = {
name: string;
age?: number;
gender?: string;
department?: string;
isRetired: boolean;
};
type PartialCustomerData = Partial<CustomerData>;
このPartialCustomerData
は、👇と同じです。
type PartialCustomerData = {
name?: string;
age?: number;
gender?: string;
department?: string;
isRetired?: boolean;
};
2-2 Required<Type>
Required<Type>
は、type
の全てのプロパティを必須にします。
type CustomerData = {
name: string;
age?: number;
gender?: string;
department?: string;
isRetired: boolean;
};
type RequiredCustomerData = Required<CustomerData>;
このRequiresCustomerData
は、👇と同じです。
type RequiredCustomerData = {
name: string;
age: number;
gender: string;
department: string;
isRetired: boolean;
};
2-3 Readonly<Type>
Readonly<Type>
は、type
の全てのプロパティを読み取り専用にします。更新などができなくなりますね。
type CustomerData = {
name: string;
age?: number;
gender?: string;
department?: string;
isRetired: boolean;
};
type ReadonlyCustomerData = Readonly<CustomerData>;
👇プロパティの更新ができなくなります。
const customerData: ReadonlyCustomerData = {
name: "shinji",
age: 28,
gender: "male",
department: " accounting",
isRetired: false,
};
//読み取り専用プロパティであるため、'name' に代入することはできません。
customerData.name = "asuka";
2-4 Record<Keys, Type>
Reacord<keys,Type>
は、プロパティのキーがkeys
でその型がType
であるオブジェクト型を返します。
type CustomerLists = Record<"shinji" | "asuka", CustomerData>;
const customerlists: CustomerLists = {
shinji: {
name: "shinji",
age: 28,
gender: "male",
department: "accounting",
isRetired: false,
},
asuka: {
name: "asuka",
age: 28,
gender: "female",
department: "sales",
isRetired: false,
},
CustomerLists
の型は👇のようになります。
type CustomerLists = {
shinji: CustomerData;
asuka: CustomerData;
}
2-5 Pick<Type, Keys>
Pick<Type,Keys>
は、型Type
からKeys
で指定したキーを含むオブジェクト型を返します。
type CustomerData = {
name: string;
age?: number;
gender?: string;
department?: string;
isRetired: boolean;
};
type CustomerNameLists = Pick<CustomerData,"name">
CustomerNameLists
の型は👇のようになります。
type CustomerNameLists = {
name: string;
}
2-6 Omit<Type, Keys>
Omit<Type,Keys>
は、型Type
からKeys
で指定したキーを除くオブジェクト型を返します。
type CustomerData = {
name: string;
age?: number;
gender?: string;
department?: string;
isRetired: boolean;
};
type CustomerNameLists = Omit<
CustomerData,
"age" | "gender" | "department" | "isRetired"
>;
CustomerNameLists
の型は👇のようになります。
type CustomerNameLists = {
name: string;
}
2-7 Exclude<UnionType, ExcludedMembers>
Exclude<UnionType, ExcludedMembers>
は、ユニオン型UnionType
から、ExcludedMembers
で指定した型を除いたユニオン型を返します。
type JobGrade = "S" | "A" | "B" | "C" | "D";
type SuperJobGrade = Exclude<JobGrade, "B" | "C" | "D">;
SuperJobGrade
の型は👇のようになります。
type SuperJobGrade = "S" | "A"
2-8 Extract<Type, Union>
Extract<Type, Union>
は、ユニオン型Type
から、Union
で指定した型を抽出したユニオン型を返します。
type JobGrade = "S" | "A" | "B" | "C" | "D";
type SuperJobGrade = Extract<JobGrade, "S" | "A">;
SuperJobGrade
の型は👇のようになります。
type SuperJobGrade = "S" | "A"
Extract<Type, Union>
は、2つのユニオン型の共通部分を抽出するのに使えます。
2-9 NonNullable<Type>
NonNullable<Type>
は、Type
から、null
とundefiend
と取り除いた型を返します。
type T1 = string | boolean | null | undefined;
type NonNullableT1 = NonNullable<T1>;
NonNullableT1
の型は👇のようになります。
type NonNullableT1 = string | boolean
2-10 Parameters<Type>
Parameters<Type>
は、関数型Type
の引数をタプル型として抽出した型を返します。
type T1 = Parameters<
(arg1: string, arg2: boolean, arg3?: number) => void
>;
T1
は、👇と同じです。
type T1 = [arg1: string, arg2: boolean, arg3?: number | undefined]
2-11 ConstructorParameters<Type>
ConstructorParameters<Type>
は、コンストラクター関数型Type
の引数をタプル型として抽出した型を返します。
class Customer {
name: string;
age: number;
isRetired: boolean;
constructor(name: string, age: number, isRetired: boolean) {
this.name = name;
this.age = age;
this.isRetired = isRetired;
}
}
type ConstructorParametersCustomer = ConstructorParameters<typeof Customer>;
ConstructorParametersCustomer
は、👇と同じです。
type ConstructorParametersCustomer = [name: string, age: number, isRetired: boolean]
2-12 ReturnType<Type>
ReturnType<Type>
は、関数型Type
の返り値の型を抽出します。
type T1 = ReturnType<() => string | number>;
T1
は、👇と同じです。
type T1 = string | number
2-13 InstanceType<Type>
InstanceType<Type>
は、コンストラクタで生成されるインスタンスの型を返します。
class Customer {
name: string;
age: number;
isRetired: boolean;
constructor(name: string, age: number, isRetired: boolean) {
this.name = name;
this.age = age;
this.isRetired = isRetired;
}
}
type T1 = InstanceType<typeof Customer>;
T1
は、👇と同じになります。
type T1 = Customer
2-14 ThisParameterType<Type>
ThisParameterType<Type>
は、this引数の型を取得できます。
type T1 = ThisParameterType<
(this: { name: string; age: number }, arg: string) => void
>;
T1
は、👇のようになります。
type T1 = {
name: string;
age: number;
}
ちなみに、2-10で紹介したParameters<Type>
では、this引数の型は取得できません。
type T2 = Parameters<
(this: { name: string; age: number }, arg: string) => void
>;
T2
は、👇のようになります。
type T2 = [arg: string]
2-15 OmitThisParameter<Type>
OmitThisParameter<Type>
は、this引数の型を取り除いた関数型を取得できます。
type T1 = OmitThisParameter<
(this: { name: string; age: number }, arg: string) => void
>;
T1
は、👇のようになります。
type T1 = (arg: string) => void
2-16 ThisType<Type>
ThisType<Type>
は、object内でのthis
の型をType
を定義します。
const obj: ThisType<{ name: string; age: number }> = {
info() {
console.log(this.name, this.age);
},
};
obj
内でのthis
は、👇のようになります。
this: {
name: string;
age: number;
}
2-17 Uppercase<StringType>
文字列のリテラル型を全て大文字にして返します。
type name = Uppercase<"Shinji">;
//type name = "SHINJI" となる
2-18 Lowercase<StringType>
文字列のリテラル型を全て小文字にして返します。
type name = Lowercase<"SHINJI">;
//type name = "shinji"となる
2-19 Capitalize<StringType>
文字列のリテラル型を最初の文字を大文字にして返します。
type name = Capitalize<"shinji">;
//type name = "Shinji"となる
2-20 Uncapitalize<StringType>
文字列のリテラル型を最初の文字を小文字にして返します。
type name = Uncapitalize<"SHINJI">;
//type name = "sHINJI"となる
3 最後に
Partial
、Required
、Readonly
、Record
、Pick
、Omit
くらいまでは普段の使うことがありましたが、その他のものは馴染みがありませんでした。
特に、this
絡みのユーティリティ型は、あまり使い所がイメージできていないので、OSSでの使われ方を探してみる、またはtype-challengesなどで、理解を深めていきたいです!
4 参考
ユーティリティ型 (utility type) | TypeScript入門『サバイバルTypeScript』
Discussion