TS-实现 Readonly

实现 Readonly

题目链接

不要使用内置的Readonly<T>,自己实现一个。

Readonly 会接收一个 泛型参数,并返回一个完全一样的类型,只是所有属性都会被 readonly 所修饰。

也就是不可以再对该对象的属性赋值。

例如:

interface Todo {
  title: string
  description: string
}

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
复制代码

一、关键词说明

Readonly

Readonly在 TS 中的源码实现:

type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};
复制代码

这个从字面意思就可以理解是将一个类型的所有成员变为只读的状态。看下面的示例,肯定可以随意给name赋值成别的字符串值。

readonly 标记的属性只能在声明时或类的构造函数中赋值。

与 ES6 中的 const 很相似,但 readonly 只能用在类(TS 里也可以是接口)中的属性上,相当于一个只有 getter 没有 setter 的属性的语法糖。

interface

interface官方链接

它相当于类型中的 JS 对象,用于对函数、类等进行结构类型检查,所谓的结构类型检查,就是两个类型的结构一样,那么它们的类型就是兼容的,这在计算机科学的世界里也被成为 “鸭子类型”。

提示 什么鸭子类型? 当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。

现在我们要这个 todo对象 做一个类型注解,根据之前提到的 “鸭子类型” 的方式,我们可以定义一个 Interface 来为它做注解:

interface Todo {
  content: string;
  user: string;
  time: string;
  isCompleted: boolean;
}

const todo: Todo = {
 // ...
}
复制代码

type生成interface

 interface IPerson {
    name: string
    age: number
    like: Array<string>
  }
  interface IPickedPerson extends Pick<IPerson, 'name' | 'like'> { } //生成新的接口
  const p: IPickedPerson = { name: 'zs', like: ['a', 'b'] }
复制代码

二、Readonly 使用方式

interface USER {
  name: string
  age: number
}

const user: USER = {
  name: 'small-yellow',
  age: 23,
}

user.name = 'yellow-dog'
复制代码

Readonly转换一下:

const user: Readonly<USER> = {
  name: 'small-yellow',
  age: 23,
}

user.name = 'yellow-dog' // 错误,因为 name 仅是只读的
user.age = 23 // 错误,因为 age 也仅是只读的
Cannot assign to 'name' because it is a read-only property.
复制代码

三、题解

interface Todo {
  title: string
  description: string
}

//就是`keyof T` 拿到 `T` 所有属性名, 然后 `in` 进行遍历, 将值赋给 `K`, 最后 `T[K]` 取得相应属性的值时将其设置为readonly。
type MyReadonly<T> = { readonly [K in keyof T]: T[K] }

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
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享