この記事は何
最近TypeScriptでクラスなどとして定義したオブジェクト型から、関数のプロパティのみを除外した型を生成したいシーンがあったので、その方法についてまとめた記事です。
TL;DR
以下の型の定義で実現できます。
type OmitFunctionNames<T> = {
[K in keyof T]: T[K] extends (...args: never[]) => unknown ? never : K;
}[keyof T];
type OmitFunctions<T> = Pick<T, OmitFunctionNames<T>>;
//これを使う
type RecursiveOmitFunctions<T> = {
[K in keyof OmitFunctions<T>]: OmitFunctions<T>[K] extends object
? RecursiveOmitFunctions<OmitFunctions<T>[K]>
: OmitFunctions<T>[K];
};
解説
ただコード紹介をしただけで終えてしまうのも味気ないので、少しだけ解説を書きます。
OmitFunctionNames<T>
type OmitFunctionNames<T> = {
[K in keyof T]: T[K] extends (...args: never[]) => unknown ? never : K;
}[keyof T];
OmitFunctionNames
は、型T
のプロパティ名のうち、関数でないものを抽出する型です。
この型を用いて、除外するプロパティを抽出します。
OmitFunctions<T>
type OmitFunctions<T> = Pick<T, OmitFunctionNames<T>>;
OmitFunctions
は、型T
から関数プロパティを除外した型を作成します。
Pick<T, OmitFunctionNames<T>>
は、型T
のうち、OmitFunctionNames<T>
で得られたプロパティ名だけを持つ新しい型を生成するという定義を行なっています。
RecursiveOmitFunctions<T>
export type RecursiveOmitFunctions<T> = {
[K in keyof OmitFunctions<T>]: OmitFunctions<T>[K] extends object
? RecursiveOmitFunctions<OmitFunctions<T>[K]>
: OmitFunctions<T>[K];
};
RecursiveOmitFunctions
は、型T
から関数プロパティを再帰的に除外した型を作成します。
プロパティにオブジェクトである場合は再帰的にRecursiveOmitFunctions<OmitFunctions<T>[K]>
を適用し、そうでない場合はそのままの型を返します。