The instructions for this challenge are:
Implement a generic
MyReadonly2<T, K>which takes two type argumentTandK.
Kspecify the set of properties ofTthat should set to Readonly. WhenKis not provided, it should make all properties readonly just like the normalReadonly<T>.
Example code that should compile correctly is provided:
interface Todo {
title: string
description: string
completed: boolean
}
const todo: MyReadonly2<Todo, 'title' | 'description'> = {
title: "Hey",
description: "foobar",
completed: false,
}
The initial type is type MyReadonly2<T, K> = any.
This challenge is not too difficult. We can approach this as two smaller problems using a union type. The resulting type should be a union of:
- An object containing all the key/value pairs which have a key in the type of
K, each converted toreadonly - An object containing all the key/value pairs which have a key not in the type of
K
These both begin with either [P in keyof T as P extends K ? P : never]: T[P] or the inverse. After this we just need to
apply +readonly to the inclusive type.
The eventual solution is:
type MyReadonly2<T, K extends keyof T = keyof T> = {
+readonly [P in keyof T as P extends K ? P : never] : T[P]
} & {
[P in keyof T as P extends K ? never : P] : T[P]
};
It’s worth noting that this is essentially a union type of our Omit and Pick implementations from earlier. As a result
we could write this more simply by using those utility types.
type MyReadOnly2<T, K extends keyof T = keyof T> = Readonly<Pick<T, K>> & Omit<T, K>;