8 - 对象部分属性只读
实现一个泛型MyReadonly2<T, K>,它带有两种类型的参数T和K。
类型 K 指定 T 中要被设置为只读 (readonly) 的属性。如果未提供K,则应使所有属性都变为只读,就像普通的Readonly<T>一样。
例如
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
Solution
type MyReadonly2<T, K extends keyof T = keyof T> = {
readonly [P in K]: T[P]
} & {
[P in keyof T as P extends K ? never : P]: T[P]
}
readonly [P in K]: T[P]: 遍历K, 将给定的属性变为readonly[P in keyof T as P extends K ? never : P]: T[P]: 分别两部分 (P in keyof T) as (P extends K ? never : P)P in keyof T: 遍历T中的属性名P extends K ? never : P:P是K的子集,说明需要设置为readonly, 由于前面已经设置过了,只需返回never, 不是K的子集,则返回P