跳到主要内容

Readonly

实现一个泛型 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

答案

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

这题不难,关键要读懂题目意思,如果传了泛型 K,那就只将泛型 K 里的属性设置为 readonly,其他的属性不变。

如果没传 K,由于这里的 K 会给一个默认的类型 = keyof T, 所以就能实现所有的属性变为只读再和一个 {} 交叉。

信息
// 看到的更简洁的答案
type MyReadonly2<T, K extends keyof T = keyof T> = Omit<T, K> &
Readonly<Pick<T, K>>;