Yuzhe's Blog

yuzhes

实现 Omit

实现 Omit

题目链接

题目

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

类型 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

解答

type MyOmit<T, K extends keyof T> = 
  {[P in keyof T as P extends K ? never: P] :T[P]}

as可以用来重映射属性名。

例如,我们声明一个使每个字符串属性名大写的类型:

type UpperProps<T> = {
  [P in keyof T as Uppercase<`${string & P}`>]: T[P]
}

interface Todo {
  title: string
  description: string
  completed: boolean
}

type TodoUpper = UpperProps<Todo>
// { TITLE: string, DESCRIPTION: string, COMPLETED: boolean }

特别的,当属性名被重映射为 never 时,它会被过滤掉。

type MyOmit<T, K extends keyof T> = 
  {
    [P in keyof T // 遍历 T 的所有属性
      as  // 重映射属性名
      P extends K // 如果属性名在 K 中
        ? never // 过滤掉
        : P // 否则保留原来的值
    ] : T[P] // 保留属性值
  }