Skip to content

对象部分属性只读

题目

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

类型 K 指定 T 中要被设置为只读 (readonly) 的属性。如果未提供K,则应使所有属性都变为只读,就像普通的Readonly<T>一样。

例如

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

解答

如果未提供K,则应使所有属性都变为只读

因此泛型需要一个默认值:

ts
type MyReadonly2<T, K extends keyof T = keyof T> = any;

K 中的属性只读,其他的维持原状

我们可以使用 Pick<T, K>Omit<T, K> 分别取出 K 的属性与剩余属性:

ts
type MyReadonly2<T, K extends keyof T = keyof T> = Omit<T, K> &
  Readonly<Pick<T, K>>;

如果不用内置属性,也可以通过返回 { never: T[Key]} 的方式来进行过滤:

ts
type MyReadonly2<T, K extends keyof T = keyof T> = {
  [Key in keyof T as Key extends K ? never : Key]: T[Key];
} & {
  readonly [Key in K]: T[Key];
};

Released under the MIT License.