Home > types-kit > SetReadonlyDeep
Make some properties (includes deep properties) in T readonly (add readonly decorator)..
Signature:
export type SetReadonlyDeep<T, K extends DeepKeys<T>> = IsNever<
Extract<K, Keys<T>>
> extends true
? // for tuple when not match the first level properties
{
[P in keyof T]: T[P] extends infer V
? V extends V
? IsObject<V> extends true
? SetReadonlyDeep<
V,
// distributed condition type
K extends `${infer Head}.${infer Tail}`
? P extends Head
? Extract<
Tail extends Tail
? `${P}.${Tail}` extends K
? Tail
: never
: never,
DeepKeys<V>
>
: never
: never
>
: V
: never
: never
}
: Simplify<
{
readonly [P in keyof T as If<
And<[IsExtends<P, Keys<T>>, IsExtends<P, K>]>,
P,
never
>]: T[P] extends infer V
? V extends V
? IsObject<V> extends true
? SetReadonlyDeep<
V,
// distributed condition type
K extends `${infer Head}.${infer Tail}`
? P extends Head
? Extract<
Tail extends Tail
? `${P}.${Tail}` extends K
? Tail
: never
: never,
DeepKeys<V>
>
: never
: never
>
: V
: never
: never
} & {
[P in keyof T as If<
And<[IsExtends<P, Keys<T>>, Not<IsExtends<P, K>>]>,
P,
never
>]: T[P] extends infer V
? V extends V
? IsObject<V> extends true
? SetReadonlyDeep<
V,
// distributed condition type
K extends `${infer Head}.${infer Tail}`
? P extends Head
? Extract<
Tail extends Tail
? `${P}.${Tail}` extends K
? Tail
: never
: never,
DeepKeys<V>
>
: never
: never
>
: V
: never
: never
}
>References: DeepKeys, IsNever, Keys, IsObject, SetReadonlyDeep, Simplify, If, And, IsExtends, Not
interface Props {
a: {
b?: number
readonly c: {
d: number
}
}
e: number
}
// Expect: {
// readonly a: {
// b?: number | undefined
// readonly c: {
// readonly d: number
// }
// }
// readonly e: number
// }
type NewProps = SetReadonlyDeep<Props, 'e' | 'a' | 'a.c.d'>