Typescript类型体操 - Readonly 2
题目
中文
实现一个通用MyReadonly2<T, K>
,它带有两种类型的参数T
和K
。
K
指定应设置为Readonly的T
的属性集。如果未提供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
English
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
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
答案
解法一,引入第三个泛型参数O
type MyReadonly2<T, K extends keyof T = keyof T, O extends keyof T = keyof T> = { readonly [P in keyof T]: T[P] } & {
[P in (O extends K ? never : O)]: T[P]
}
解法二,借助MyOmit MyExclude辅助
type MyExclude<T, K> = T extends K ? never : T;
type MyOmit<T, K extends keyof T> = { [P in MyExclude<keyof T, K> ]: T[P] }
type MyReadonly2<T, K extends keyof T = keyof T> = { readonly [P in keyof T]: T[P] } & MyOmit<T, K>