Deep Readonly
挑战
实现一个通用的 DeepReadonly<T>
以递归的方式只读化(readonly
)对象及其子对象
的每个属性。
你可以假设在这个挑战中我们只处理对象。无需要考虑数组、函数、类等。但是,你仍然可 以通过尽可能多的覆盖不同的案例来挑战自己。
例如:
type X = {
x: {
a: 1;
b: "hi";
};
y: "hey";
};
type Expected = {
readonly x: {
readonly a: 1;
readonly b: "hi";
};
readonly y: "hey";
};
const todo: DeepReadonly<X>; // should be same as `Expected`
解答
在这个挑战中,我们需要创建相同的 Readonly<T>
类型。唯一
的区别是我们需要使它递归化。
让我们从经典开始,实现常规的 Readonly<T>
类型:
type DeepReadonly<T> = { readonly [P in keyof T]: T[P] };
但是,正如你已经知道的,这个类型不会将所有内容都设为只读,仅是没有深度的字段。原
因是当我们的 T[P]
不是原始类型,而是一个对象时,它会按原样传递它,且不会将其属
性设为只读。
因此,我们需要将 T[P]
替换为 DeepReadonly<T>
的递归用法。不过,在使用递归时
不要忘记基本情况。
算法很简单。如果 T[P]
是一个对象,我们继续调用 DeepReadonly
,否则返回 T[P]
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends Record<string, unknown>
? DeepReadonly<T[P]>
: T[P];
};
评论