挑战
实现一个泛型 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`解答
这道题和常规的 Readonly<T> 不同的是,我们需要让它递归化。
我们从常规的 Readonly<T> 开始:
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P];
};这种实现只会把没有深度的字段设为只读,如果 T[P] 不是基本类型,而是一个对象时,会按原样传递,并且不会将其属性设为只读。
所以如果 T[P] 不是基本类型时,我们需要递归调用 DeepReadonly<T>,直到 T[P] 为基本类型。
判断 T[P] 是否为基本类型有多种写法,我这里使用了 keyof T[P] extends never 的写法。
所以最终实现为:
type DeepReadonly<T> = {
readonly [P in keyof T]: keyof T[P] extends never ? T[P] : DeepReadonly<T[P]>;
};