
TypeScript の高度な型 ⑨ 再帰的なUtility Types
TypeScript 2.8 以降では、Mapped TypesとConditional Types を併用することで、
再帰的な型変換が可能です。
今回の記事では紹介する型は、リスト6-3-24に示した既存の型に対して変換を行うものとします。
interface User{
name: string
age: number
gender: 'male' | 'female' | 'other'
birth: {
day: Date
place?: {
countory?: string | null
state?: string
}
}
}
isPrimitive型
Object型およびArray型に該当するか否かを判定する型です。
(該当しなければPrimitive型とみなす)
再帰的な型変換に、この型を利用します。
type Unbox<T> = T extends {[k: string]: infer U} ? U
: T extends (infer U)[] ? U
: T
type isPrimitive<T> = T extends Unbox<T> ? T : never
DeeReadonly型
再帰的にReadonly変換する型です。
type DeepReadonly<T> = {
reaonly [P in keyof T]: T[P] extends isPrimitive<T[P]>
? T[P]
: DeepReadonly[T[P]]
}
type DeepReadonlyWrapUser = DeepReadonly<User>
型推論結果
type DeepreadonlyWrapUser = {
name: string
readonly age: number
readonlu gender: 'make' | 'female' | 'other'
readonly birth: {
readonly day: Date
readonly place?: {
readonly countoru?: string : null
readonly state?: string
}
}
DeepRequired型
再帰的にRequired変換する型です。
type DeepRequired<T> = {
[P in keyof T]-?: T[P] extends isPrimitive<T[P]>
? T[P]
: DeepRequired<T[P]>
}
type DeepRequiredWrapUser = Deeprequired<user>
推論結果
type DeepPartialWrapUser = {
name?: string| undefined
age?: number | undefined
gender? : 'male', 'famale' | 'other' | undefined
birth?: {
day? date | undefind
place? : {
countory? : string | null | undefined
state? : string| undefined
} | underfined
} | underfined
}
DeepNullable型
再帰的にNullable変換する型です。
type DeepNullable<T> = {
[P in keyof T]?: T[P] extends isPrimitive<T[P]>
? T[P] | null
: DeepNullable<T[P]>
}
type DeepNullableWrapUser = DeepNullable<user>
type DeepPartialWrapUser = {
name?: string| null | undefined
age?: number | null | undefined
gender? : 'male', 'famale' | 'other' | null | undefined
birth?: {
day? date | undefind
place? : {
countory? : string | null | undefined
state? : string | null | undefined
} | null | underfined
} | null | underfined
}
DeepNonNullable 型
再帰的にNullable変換する型です。
type DeepNonNullable<T> = {
[P in keyof T]-?: T[P] extends isPrimitive<T[P]>
? Exclude<T[P], null | undefinned>
: DeepNonNullabel<T[P]>
}
type DeepNoNullableWrapUser = DeepNonNullable<User>
型推論結果
type DeepNonNullableWrapUser = {
name: string
age: number
gender : 'male', 'famale' | 'other'
birth: {
day Date
place : {
countory: string
state: string
}
}
}