小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
背景
大家好,我是梅利奥猪猪。上次说了Readonly,其实大家不难发现,源码的实现只要看了都非常容易理解,不要脸的猪猪,讲解方式的本质就是翻译官方文档!所以这次我们换一种方式讲解,自己尝试实现,然后在看源码分析(其实一样是水文啦哈哈),那我们废话不多说,直接开始今天的主角-Record
正文
官方例子
先来看下官方的例子,以及说明(要知道它干嘛用的才能去实现)
Constructs an object type whose property keys are Keys and whose property values are Type. This utility can be used to map the properties of a type to another type.
interface CatInfo {
age: number;
breed: string;
}
type CatName = "miffy" | "boris" | "mordred";
const cats: Record<CatName, CatInfo> = {
miffy: { age: 10, breed: "Persian" },
boris: { age: 5, breed: "Maine Coon" },
mordred: { age: 16, breed: "British Shorthair" },
};
cats.boris;
从官方例子中能看到,我们变量cats,是个对象,它的key值就是我们之前定义的type CatName,XDM如果尝试删掉其中一个key就会报错, catName必须都要包含(所以我们实现也需要这样),然后value就是我们定义的接口CatInfo,即每只猫的猫属性都是CatInfo,知道这些信息我们就可以尝试实现了
尝试实现
我们先把最简单的架子搭好
type MyRecord<K, T> = {
}
为什么泛型会写两个,很简单,我们使用的时候就是Record<xxx,xxx>(这就是现在流行的废话文学了吧),起名k和t,是key和type的意思,接下来,我们可以想下,一般我们对象的key的值,一般是不是就是字符串,数字,还有个大家可能接触比较少的symbol,所以我们的架子又可以进化成如下代码
type MyRecord<K extends string | number | symbol, T> = {
}
联合类型代表的是或者的意思,翻译下就是,可以是string,可以是number,也可以是symbol任意一个类型,还记得前面我们说的,XDM如果尝试删掉其中一个key就会报错, catName必须都要包含(所以我们实现也需要这样)所以接下来我们就要实现这个,遍历开始!
type MyRecord<K extends string | number | symbol, T> = {
[P in K]: T
}
上面的代码在遍历后,我直接就实现了,因为T就是我们最终Value的类型,所以我们遍历所有key之后,他们的value类型就是我们的T,实现结束,最后我们在来看下源码实现和我们有什么区别吧
源码讲解
上源码看下
/**
* Construct a type with a set of properties K of type T
*/
type Record<K extends keyof any, T> = {
[P in K]: T;
};
看上去几乎一毛一样,唯一的区别就是keyof any,这应该是我们的知识盲区了,我们赶快写个ts看下type testKey = keyof any,当我们把鼠标移入testKey的时候就能看到
这不就是我们前面写的string | number | symbol嘛!好的大功告成,XDM学会了嘛,欢迎和小白的我一起讨论学习!今天的水文就到这!