Skip to main content

Readonly2

introduction#

Implement a generic MyReadonly2<T, K> which takes two type argument T and K.

K specify the set of properties of T that should set to Readonly. When K is not provided, it should make all properties readonly just like the normal Readonly<T>.

For example

ts
interface Todo {
title: string
description: string
completed: boolean
}
const todo: MyReadonly2<Todo, 'title' | 'description'> = {
title: "Hey",
description: "foobar",
completed: false,
}
todo.title = "Hello" // Error: cannot reassign a readonly property
todo.description = "barFoo" // Error: cannot reassign a readonly property
todo.completed = true // OK
ts
interface Todo {
title: string
description: string
completed: boolean
}
const todo: MyReadonly2<Todo, 'title' | 'description'> = {
title: "Hey",
description: "foobar",
completed: false,
}
todo.title = "Hello" // Error: cannot reassign a readonly property
todo.description = "barFoo" // Error: cannot reassign a readonly property
todo.completed = true // OK
View on GitHub

start point#

ts
/* _____________ Your Code Here _____________ */
 
type MyReadonly2<T, K> = any
 
/* _____________ Test Cases _____________ */
type cases = [
Expect<Alike<MyReadonly2<Todo1, 'title' | 'description'>, Expected>>,
Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.
Expect<Alike<MyReadonly2<Todo2, 'title' | 'description'>, Expected>>,
Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.
]
 
interface Todo1 {
title: string
description?: string
completed: boolean
}
 
interface Todo2 {
readonly title: string
description?: string
completed: boolean
}
 
interface Expected {
readonly title: string
readonly description?: string
completed: boolean
}
 
Try
ts
/* _____________ Your Code Here _____________ */
 
type MyReadonly2<T, K> = any
 
/* _____________ Test Cases _____________ */
type cases = [
Expect<Alike<MyReadonly2<Todo1, 'title' | 'description'>, Expected>>,
Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.
Expect<Alike<MyReadonly2<Todo2, 'title' | 'description'>, Expected>>,
Type 'false' does not satisfy the constraint 'true'.2344Type 'false' does not satisfy the constraint 'true'.
]
 
interface Todo1 {
title: string
description?: string
completed: boolean
}
 
interface Todo2 {
readonly title: string
description?: string
completed: boolean
}
 
interface Expected {
readonly title: string
readonly description?: string
completed: boolean
}
 
Try
take the challenge

my solutions#

Spoiler warning // Click to reveal answer
ts
type MyOmit<T, K extends string | number | symbol> = {
[Key in Exclude<keyof T, K>]: T[Key]
}
 
type MyReadonly2<T, K extends keyof T = keyof T> = {
readonly [Key in K]: T[Key]
} & MyOmit<T, K>
 
Try
ts
type MyOmit<T, K extends string | number | symbol> = {
[Key in Exclude<keyof T, K>]: T[Key]
}
 
type MyReadonly2<T, K extends keyof T = keyof T> = {
readonly [Key in K]: T[Key]
} & MyOmit<T, K>
 
Try
view more solutions