木灵鱼儿
阅读:918
索引类型,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"]));
当我们需要遍历一些对象的key值时,可能会有这种情况,但是这样写ts无法正确的限制你的keys数组是否都是属于obj的值。
使用ts不就是为了避免这种问题吗,再静态的时候就把错误提示出来,但是上面那段代码,我们consoe最终输出却是这样的。
[1,2]
[undefined,undefined]
为了避免出现undefined,我们需要利用泛型来约束第一个参数obj,然后通过keyof T
索引类型查询操作符来约束keys参数必须是T中存在的key。
改写
function getObjVal<T>(obj:T,keys:(keyof T)[]) {
return keys.map(key => obj[key]);
}
这样,当keys的值是不存在于obj的key时就会警告报错。但是需要注意keyof T
用括号包裹起来,不然无法正确的识别。
keyof T
获得的是联合泛型T的key值,大概示意如下:
"a" | "b" | "c" //字面量的联合属性
当然这种不太好看,我们可以利用泛型的继承特性,去除括号包裹
function getObjVal<T,K extends keyof T>(obj:T,keys:K[]) {
return keys.map(key => obj[key]);
}
当我们鼠标放在函数名上时,可以看到函数的返回值也有了更准确的类型约束
function getObjVal<T, K extends keyof T>(obj: T, keys: K[]): T[K][]
T[K][]
成了返回类型约束,返回一个数组,数组的值必须是泛型T对应的K泛型得到的值。
版权申明
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿 - 有梦就能远航站点。未经许可,禁止转载。
相关推荐
正确使用vue3的ts类型声明
前言使用了ts最头疼的是什么,除了类型声明应该没有第二家了,那么在vue3中如何正确的声明ts类型,代表着我们踏出了认识vue3的第一步,这非常重要,所以为此水个文章,分享给有需要的人。Volar 插件一开始我对于Volar并没有太大的需要,因为一直使用的Vetur,而且这个插件刚出来时并不完善,各种视频up讲的那个一键分屏功能其实也并不好用,虽然是个很有意思的东西,但是没有那种非要使用它的点,所以当时的我怀着这么一个疑问?为什么要用Volar ?现在我就通过两张图告诉你,它有多香!我们在template里面写代码,绑定变量最烦的是什么,就是我们写了个对象,但是忘了它的属性有哪些啊,使用...

映射类型,对象属性批量设置约束
批量设置属性全部只读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 属性“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...
