yunliuyan / type-challenges

typescript-challenges
0 stars 2 forks source link

00008-medium-deep-readonly #8

Open yunliuyan opened 11 months ago

yunliuyan commented 11 months ago

深度 Readonly 中等 #readonly #object-keys #deep

by Anthony Fu @antfu

接受挑战    English 日本語 한국어

由谷歌自动翻译,欢迎 PR 改进翻译质量。

实现一个通用的DeepReadonly<T>,它将对象的每个参数及其子对象递归地设为只读。

您可以假设在此挑战中我们仅处理对象。数组,函数,类等都无需考虑。但是,您仍然可以通过覆盖尽可能多的不同案例来挑战自己。

例如

type X = { 
  x: { 
    a: 1
    b: 'hi'
  }
  y: 'hey'
}

type Expected = { 
  readonly x: { 
    readonly a: 1
    readonly b: 'hi'
  }
  readonly y: 'hey' 
}

type Todo = DeepReadonly<X> // should be same as `Expected`

测试案例:

import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<DeepReadonly<X>, Expected>>,
]

type X = {
  a: () => 22
  b: string
  c: {
    d: boolean
    e: {
      g: {
        h: {
          i: true
          j: 'string'
        }
        k: 'hello'
      }
      l: [
        'hi',
        {
          m: ['hey']
        },
      ]
    }
  }
}

type Expected = {
  readonly a: () => 22
  readonly b: string
  readonly c: {
    readonly d: boolean
    readonly e: {
      readonly g: {
        readonly h: {
          readonly i: true
          readonly j: 'string'
        }
        readonly k: 'hello'
      }
      readonly l: readonly [
        'hi',
        {
          readonly m: readonly ['hey']
        },
      ]
    }
  }
}

返回首页 分享你的解答 查看解答

相关挑战

7・实现 Readonly 8・Readonly 2
yunliuyan commented 11 months ago

思路

遍历对象属性,设为readonly。 判断属性对应的值是否可遍历,若可以遍历,则递归使用DeepReadonly,否则为属性值。 关键属性的值的判断,代码: keyof T[key] extends never ? 【基础值】 : 【对象】

代码实现

type DeepReadonly<T>  = {
  readonly [key in keyof T] : keyof T[key] extends never? DeepReadonly<T[key]> : T[key] ; 
}
Janice-Fan commented 11 months ago

type DeepReadonly = { readonly [k in keyof T]: T[k] extends object ? DeepReadonly<T[k]> : T[k]; }

wudu8 commented 11 months ago
/**
 * 实现一个readonly类型,针对所有对象属性或基本类型属性只读
 */
type DeepReadOnly<T> = {
    readonly [k in keyof T]: T[k] extends object ? DeepReadOnly<T[k]> : T[k];
};

interface deepReadonlyType {
    name: string;
    description: string;
    meta: {
    description: string;
    meta2: {
      description: string;
    };
    };
}

const deepReadonlyTest: DeepReadOnly<deepReadonlyType> = {
    name: "字节猿",
    description: "字节猿喜欢readonly",
    meta: {
    description: "ILoveReadOnly类型并不支持深层只读",
    meta2: {
      description: "ILoveReadOnly类型并不支持深层只读",
    },
    },
};

deepReadonlyTest.name = "abc"; // Error: Cannot assign to 'name' because it is a read-only property.ts(2540)
deepReadonlyTest.meta.description = "abc"; // Error: Cannot assign to 'name' because it is a read-only property.ts(2540)
deepReadonlyTest.meta.meta2.description = "abc"; // Error: Cannot assign to 'name' because it is a read-only property.ts(2540)
wudu8 commented 11 months ago

思路

遍历对象属性,设为readonly。 判断属性对应的值是否可遍历,若可以遍历,则递归使用DeepReadonly,否则为属性值。 关键属性的值的判断,代码: keyof T[key] extends never ? 【基础值】 : 【对象】

代码实现

type DeepReadonly<T>  = {
  readonly [key in keyof T] : keyof  T[key] extends object ? DeepReadonly<T[key]> : T[key] ; 
}

keyof T[key] 不起作用的

Naparte commented 11 months ago
type DeepReadonly<T> = { readonly [key in keyof T]: T[key] extends object ? DeepReadonly<T[key]> : T[key] }

type X = {
  x: {
    a: 1
    b: 'hi'
  }
  y: 'hey'
}

type Expected = {
  readonly x: {
    readonly a: 1
    readonly b: 'hi'
  }
  readonly y: 'hey'
}

type Todo = DeepReadonly<X> 
liangchengv commented 11 months ago
type DeepReadonly<T> = {
  readonly [P in keyof T]: T[P] extends object
    ? DeepReadonly<T[P]>
    : T[P];
};