木灵鱼儿
阅读:986
映射类型,对象属性批量设置约束
批量设置属性全部只读
interface ObjInterface {
a: number;
b: number;
c: number;
}
//全部设为只读
type readonlyObj = Readonly<ObjInterface>;
鼠标移动到readonlyObj
可以发现所有的属性全部设置为只读了。
type readonlyObj = {
readonly a: number;
readonly b: number;
readonly c: number;
}
我们按住ctrl+鼠标左键点击Readonly
;可以看到ts的相关实现:
type Readonly<T> = {
readonly [P in keyof T]: T[P];
}
ts官方定义了一个Readonly类型,它有一个泛型T,类型的属性会通过keyof
拿到T的所有key的联合类型,然后P in
相当于进行了一个for循环,把联合类型中的对应的每个key值都赋值到P上,P自身又readonly
了,值则是T[P],可以理解为对象obj[key]
。
批量可选
interface ObjInterface {
a: number;
b: number;
c: number;
}
//全部设为可选
type partialObj = Partial<ObjInterface>;
鼠标移动到partialObj
可以看到所有的属性都变成了可选
type partialObj = {
a?: number;
b?: number;
c?: number;
}
我们按住ctrl+鼠标左键点击Partial
;可以看到ts的相关实现:
type Partial<T> = {
[P in keyof T]?: T[P];
}
原理和批量只读一样,只是这里改用了?:
可选了。
指定属性key生成新的声明
我们需要生成一个新的类型声明,但是只需要ObjInterface
的a和b属性。
interface ObjInterface {
a: number;
b: number;
c: number;
}
//生成指定属性声明
type pickObj = Pick<ObjInterface,"a"|"b">
得到如下:
type pickObj = {
a: number;
b: number;
}
Pick
的实现:
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
}
它有两个泛型,第一个是源参,第二个是需要使用到的key值联合类型,并且必须是来源于T的。
剩下就是in循环了。
已知属性赋值到指定key并生成新的声明
比如说我有一个对象,里面有a、b、c
三个属性都是布尔值,这三个key对应的都是同一个类型。
interface ObjInterface {
a: number;
b: number;
c: number;
}
//已知属性赋值到指定key并生成新的声明
type recordObj = Record<"a"|"b"|"c",ObjInterface>
得到:
type recordObj = {
a: ObjInterface;
b: ObjInterface;
c: ObjInterface;
}
Record实现:
type Record<K extends string, T> = {
[P in K]: T;
}
这里就不太清楚为啥K要继承string
实战例子:
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;
版权申明
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿 - 有梦就能远航站点。未经许可,禁止转载。
相关推荐
正确使用vue3的ts类型声明
前言使用了ts最头疼的是什么,除了类型声明应该没有第二家了,那么在vue3中如何正确的声明ts类型,代表着我们踏出了认识vue3的第一步,这非常重要,所以为此水个文章,分享给有需要的人。Volar 插件一开始我对于Volar并没有太大的需要,因为一直使用的Vetur,而且这个插件刚出来时并不完善,各种视频up讲的那个一键分屏功能其实也并不好用,虽然是个很有意思的东西,但是没有那种非要使用它的点,所以当时的我怀着这么一个疑问?为什么要用Volar ?现在我就通过两张图告诉你,它有多香!我们在template里面写代码,绑定变量最烦的是什么,就是我们写了个对象,但是忘了它的属性有哪些啊,使用...

索引类型,key的约束
再for循环中我们经常遇到类似这种写法const obj = { a: 1, b: 2, c: 3 }; //遍历obj拿到指定key对应的val数组 function getObjVal(obj:any,keys:string[]) { return keys.map(key => obj[key]); } console.log(getObjVal(obj, ["a", "b"])); console.log(getObjVal(obj, ["d", "e"]...
关于ts 属性“xxx”没有初始化表达式,且未在构造函数中明确赋值的解决方案
ts默认要求class中声明的属性必须初始化,所以,如果存在没有被初始化的属性,就会报这个错误。如果我们让他或者等于null,那么在调用属性的时候又会提示值可能为null,极度麻烦class A { data: { name: string } | null = null; } const a = new A(); console.log(a.data.name);然后你又不得不搞个非空断言。console.log((a.data!).name);每次都这么写非常麻烦。赋值方案既然他要赋值那么我们就赋值class A { data: { name: string }; c...
