Skip to content

Latest commit

 

History

History
124 lines (115 loc) · 3.86 KB

File metadata and controls

124 lines (115 loc) · 3.86 KB

Home > types-kit > SetReadonlyDeep

SetReadonlyDeep type

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

Example

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'>