题目
实现一个类型工具 MyReadonly<T>,接收一个类型参数T,返回一个和T完全一样的类型,只不过所有的属性都被 readonly 修饰。
例如:
interface Todo {
title: string
description: string
}
// 现在 todo 的 title 和 description 属性都是 readonly 的了。
const todo: MyReadonly<Todo> = {
title: "Hey",
description: "foobar"
}
todo.title = "Hello" // Error: cannot reassign a readonly property
todo.description = "barFoo" // Error: cannot reassign a readonly property
原题链接
思路
类比 JavaScript
类比 JavaScript,就是实现一个函数:
这个函数接收一个老对象,创建一个新对象,把老对象的所有属性名都加上 readonly 前缀, 再拷贝给新对象,返回新对象。
function MyReadonly(obj) {
const readonlyObj = {};
for (const key in obj) {
readonlyObj["readonly_" + key] = obj[key];
}
return readonlyObj;
}
提取逻辑点
1. 返回一个对象
2. 遍历一个对象的所有属性
3. 把对象的所有属性都加上 readonly 前缀
4. 提取对象特定属性的值
再把逻辑点翻译成 typescript 即可。
翻译成 TypeScript
用 typescript 实现上述逻辑点如下。
返回一个对象
// 返回一个 {} 即可
type MyReadonly<T> = {};
遍历一个对象的所有属性
通过 [P in K] 来遍历,这里的 K 得是一个 联合类型,如 'a'|'b'|'c',而 T 是一个 interface/对象type,所以需要通过 keyof 获取 T 的属性联合类型。
[P in keyof T]
把对象的所有属性都加上 readonly 前缀
通过 readonly 关键字即可。
readonly [P in keyof T]
提取对象特定属性的值
通过 [] 提取,本例中以 T[P] 获取。
readonly [P in keyof T]: T[P]
实现
综上所述,最终的类型工具 MyReadonly 实现为:
type MyReadonly<T> = {
readonly [P in keyof T]: T[P];
}