Typescript类型体操 - Readonly 2

题目

中文

实现一个通用MyReadonly2<T, K>,它带有两种类型的参数TK

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>

在线演示

posted @ 2022-09-01 21:23  Laggage  阅读(77)  评论(0编辑  收藏  举报