type Base = {
id: number
title: string
address: {
street: string
city: string
}
}
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
}
type DeepReadonlyBase = DeepReadonly<Base>
const todo: DeepReadonlyBase = {
id: 1,
title: 'Hello',
address: {
street: '123',
city: 'world'
}
}
Solution by semet #34642
Use recursive types. We should check T's recursive ending condition.
type DeepReadonly<T> = T extends symbol | Function ? T: {
readonly [K in keyof T]: DeepReadonly<T[K]>;
}
Solution by dev-jaemin #34631
type DeepReadonly<T> = {
readonly [P in keyof T]:
keyof T[P] extends never
? T[P]
: DeepReadonly<T[P]>
}
Solution by binhdv155127 #34612
type DeepReadonly<T> = T extends object
? (
T extends [ infer A, ...infer B ]
? readonly [ DeepReadonly<A>, ...DeepReadonly<B> ]
: (
T extends Function
? T
: {
readonly [P in keyof T]: DeepReadonly<T[P]>
}
)
)
: T
Solution by DevShinnThant #34561
type DeepReadonly<T> =
T extends Function ? T :
T extends object ? { readonly [P in keyof T]: DeepReadonly<T[P]> } :
T
Solution by emen #34492
最初的答案:
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends Object ? DeepReadonly<T[K]> : T[K];
}
运行之后发现第一个案例无法通过,究其原因,对于案例中的函数,也会被默认为一个对象,由此遇到函数就会进行无限的递归调用。
//解法一:将函数作为基本类型一起归类为不需要递归调用
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends string | number | null | undefined | boolean | ((...args: any[]) => any) ? T[K] : DeepReadonly<T[K]>;
}
//解法二:由于函数不能再拆分成更加基本的类型,可以采用never类型进行判断
type DeepReadonly<T>={
readonly [K in keyof T]:T[K] extends never?T[K]:DeepReadonly<T[K]>
}
Solution by wxh-cyber #34476
type DeepReadonly<T> = T extends never ? T : {
readonly [P in keyof T]: DeepReadonly<T[P]>
}
Solution by ktim816 #34432
type DeepReadonly<T> = {
readonly [K in keyof T]: keyof T[K] extends never ? T[K] : DeepReadonly<T[K]>
}
Solution by rookie-luochao #34369
type DeepReadonly<T> = T extends any ?
keyof T extends never ? T : {
readonly [P in keyof T]: keyof T[P] extends never ? T[P]: DeepReadonly<T[P]>
}
: never;
Solution by leaderiop #34234
type DeepReadonly<T extends {}> = {
readonly [k in keyof T]: T[k] extends Function ? T[k] // 函数不需要递归
: T[k] extends {} ? DeepReadonly<T[k]> : T[k] // 如果是对象继续递归
}
Solution by quitone #34203
객체의 프로퍼티와 모든 하위 객체를 재귀적으로 읽기 전용으로 설정하는 제네릭 DeepReadonly<T>
를 구현하세요.
이 챌린지에서는 타입 파라미터 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`
type DeepReadonly<T> = {
readonly [key in keyof T]: T[key] extends object
? DeepReadonly<T[key]>
: T[key];
};
type Y1 = {
readonly a: DeepReadonly<() => 22>;
readonly b: string;
readonly c: DeepReadonly<{
d: boolean;
e: {
g: {
h: {
i: true;
j: "string";
다음과 작성했지만 예외 케이스를 통과하지 못했습니다. 제귀의 형태가 다소 이상하게 진행됨을 확인할 수 있었습니다. 저는 그 이유가 정확히 object를 찾아낼 방법이 필요하다고 생각했습니다. (원시타입이 아닌지)
keyof는 객체 타입의 모든 키를 유니언 타입으로 반환합니다. 예를 들어, 객체 타입이 { a: string, b: number }라면, keyof { a: string, b: number }는 'a' | 'b'가 됩니다.
never는 TypeScript에서 어떤 값도 가질 수 없는 타입을 의미합니다. 예를 들어, 함수가 항상 예외를 던지거나 끝나지 않는 경우 그 반환 타입은 never가 됩니다. 또한, 빈 객체의 키 타입을 keyof로 추출하려고 하면 never가 됩니다
type DeepReadonly<T> = {
readonly [K in keyof T]: keyof T[K] extends never ? T[K] : DeepReadonly<T[K]>;
};
type Y1 = {
readonly a: () => 22;
readonly b: string;
readonly c: DeepReadonly<{
d: boolean;
e: {
g: {
h: {
i: true;
j: "string";
/* _____________ 여기에 코드 입력 _____________ */
type DeepReadonly<T> = {
readonly [key in keyof T]: keyof T[key] extends never
? T[key]
: DeepReadonly<T[key]>;
};
/* _____________ 테스트 케이스 _____________ */
import type { Equal, Expect } from "@type-challenges/utils";
type cases = [
Expect<Equal<DeepReadonly<X1>, Expected1>>,
Expect<Equal<DeepReadonly<X2>, Expected2>>
];
type X1 = {
a: () => 22;
b: string;
c: {
d: boolean;
e: {
g: {
h: {
i: true;
j: "string";
};
k: "hello";
};
l: [
"hi",
{
m: ["hey"];
}
];
};
};
};
type X2 = { a: string } | { b: number };
type Expected1 = {
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"];
}
];
};
};
};
type Expected2 = { readonly a: string } | { readonly b: number };
Solution by adultlee #34130
// 函数要单独考虑
type DeepReadonly<T extends object> = T extends any ? {
readonly [P in keyof T]: T[P] extends object ? (T[P] extends Function ? T[P] : DeepReadonly<T[P]>) : T[P]
} : never
Solution by ouzexi #33986
type Primitive = string | number | boolean | bigint | symbol | undefined | null
type Builtin = Primitive | Function | Date | Error | RegExp
type DeepReadonly<T> = T extends Builtin
? T
: T extends Map<infer K, infer V>
? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>>
: T extends ReadonlyMap<infer K, infer V>
? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>>
: T extends WeakMap<infer K, infer V>
? WeakMap<DeepReadonly<K>, DeepReadonly<V>>
: T extends Set<infer U>
? ReadonlySet<DeepReadonly<U>>
: T extends ReadonlySet<infer U>
? ReadonlySet<DeepReadonly<U>>
: T extends WeakSet<infer U>
? WeakSet<DeepReadonly<U>>
: T extends Promise<infer U>
? Promise<DeepReadonly<U>>
: T extends {}
? { readonly [K in keyof T]: DeepReadonly<T[K]> }
: Readonly<T>
Solution by notsecret32 #33888
type DeepReadonly<T> = keyof T extends never ? T : {
readonly [K in keyof T]: DeepReadonly<T[K]>
}
Solution by Danny101201 #33808
type DeepReadonly<T> = {
readonly [P in keyof T]: keyof T[P] extends never
? T[P]
: DeepReadonly<T[P]>
}
Solution by laplace1009 #33714
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object
? T[K] extends Function
? T[K]
: DeepReadonly<T[K]>
: T[K];
};
Solution by Alex-Nicalace #33668
// 你的答案
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends Function ? T[P] :DeepReadonly<T[P]>
}
Solution by heyuelan #33660
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
Solution by OgabekYuldoshev #33584
type DeepReadonly<T> = {
readonly [Prop in keyof T]: T[Prop] extends (...args: any) => any
? T[Prop]
: T[Prop] extends object
? DeepReadonly<T[Prop]>
: T[Prop];
};```
Solution by Kolufs #33537
type DeepReadonly<T> = {
readonly [P in keyof T]: keyof T[P] extends never ? T[P] : DeepReadonly<T[P]>;
};
Solution by partiality #33344
// 你的答案
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
Solution by 2531800823 #33239
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends Function ? T[P] : DeepReadonly<T[P]>
}
Solution by Tubring25 #33224
type Builtin = Function | Date | Error | RegExp;
type DeepReadonly<T> = T extends Builtin ? T : {
readonly [K in keyof T]: DeepReadonly<T[K]>
}
Solution by daishi-motoyama #33186
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends Function ? T[P] : DeepReadonly<T[P]>
}
Solution by KenjiGinjo #33090
// your answers
type DeepReadonly<T> = T extends unknown ? {
readonly [P in keyof T]: T[P] extends Function
? T[P]
: T[P] extends object
? DeepReadonly<T[P]>
: T[P]
} : never
Solution by KeithChou #33079
type DeepReadonly<T> = T extends Function
? T
: {readonly [P in keyof T]: DeepReadonly<T[P]>}
Solution by Taneros #33014
// 你的答案
type DeepReadonly<T> = {
readonly [P in keyof T]: keyof T[P] extends never ? T[P] : DeepReadonly<T[P]>
}
Solution by Mohaiyo #32957
/**
* T extends Record<string, unknown> | Array<unknown>:
* 这个条件表达式表示我们希望泛型 T 能够接受任意类型,
* 但是我们只关注对象类型(使用 Record<string, unknown> 表示)和数组类型(使用 Array<unknown> 表示)。
? { readonly [P in keyof T]: DeepReadonly<T[P]> }:
这是条件类型的第一个分支。当 T 是对象类型时,我们使用映射类型来递归地处理对象的每个属性。
对于对象的每个属性 P,我们将其设为只读,并递归地调用 DeepReadonly 泛型来处理属性值 T[P],以确保其嵌套对象也被设为只读。
: T:这是条件类型的第二个分支。当 T 不是对象类型时(例如字符串、数字等基本类型),我们不做任何处理,直接返回 T。
*/
type DeepReadonly<T> = T extends Record<string, unknown> | Array<unknown>
? { readonly [P in keyof T]: DeepReadonly<T[P]> }
: T;
Solution by CAN1177 #32855
// 解答をここに記入
type DeepReadonly<T> = {
readonly [Key in keyof T]: T[Key] extends Function
? T[Key]
: T[Key] extends object
? DeepReadonly<T[Key]>
: T[Key];
}
readonly
にするため、各プロパティの前にreadonly
を記述。
DeepReadonly
を適用し、第2階層目以降も読み取り専用へ変更する。Solution by Yasunori-aloha #32811
type DeepReadonly<T> =
T extends T ? keyof T extends never
? T
: { readonly [k in keyof T]: DeepReadonly<T[k]> }
: never
Solution by sunhuoxyr #32810