再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泛型得到的值。

分类: TypeScript 标签: TypeScript索引类型keyof T泛型约束

评论

暂无评论数据

暂无评论数据

目录