以下のようなコードのContent型のプロパティから、OrFunction内の関数定義のみを取り除いた型(Union型の一部を取り除いた型)を作ることができます。
main.ts
type OrFunction<T> = T | ((val: string) => T);
interface Content {
id: string;
id2?: number;
key: OrFunction<string>;
value?: OrFunction<boolean>;
names?: Array<OrFunction<string>>;
names2: Array<OrFunction<string>>;
value2?: Array<Array<OrFunction<string>>>;
}
Conditional typesは再帰的定義ができないようなので、Arrayのネスト分の定義が必要になるのが惜しいですが、以下のような定義をしておくと
sample.ts
type Plain<T> = { [P in keyof T]: ExcludeArray<T[P], (val: any) => any> };
type ExcludeArray<T, U> = T extends Array<infer R> ? Array<ExcludeArray2<R, U>> : Exclude<T, U>;
type ExcludeArray2<T, U> = T extends Array<infer R> ? Array<Exclude<R, U>> : Exclude<T, U>;
Plain<Content>
は以下のような型になります。
{
id: string;
id2?: number;
key: string;
value?: boolean;
names?: Array<string>;
names2: Array<string>;
value2?: Array<Array<string>>;
}
Mapped typesは一見難しそうですが、{ [P in keyof T]: T[P] }
の基本的な形を覚えておけばOKです。
Conditional typesの導入とともに入ったExclude
型は便利ですね。