我是靠谱客的博主 危机钢铁侠,最近开发中收集的这篇文章主要介绍Ts keyof,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

索引查询 keyof

keyof可以用于获取某种类型的所有键,其返回类型是联合类型

接口

interface Person {
name: string;
age: number;
location: string;
}
type K1 = keyof Person; // "name" | "age" | "location"
type K2 = keyof Person[];
// number | "length" | "push" | "concat" | ...
type K3 = keyof { [x: string]: Person };
// string | number

class Person {
name: string = 'Mike';
}
let sname = keyof Person
sname = 'name'

如果把sname = 'name' 改为sname = 'yui'的话,TypeScript 编译器会提示以下错误信息:

Type '"yui"' is not assignable to type '"name"'.

解释:

keyof Person 获取到的类型是'name'

举个简单的例子:

let a : 1
a = 1
a = 2

以上的例子,将a的类型为1,那么这个变量的值只能是1,不能为其他的,当a = 2执行的时候,就会报错

基本数据类型

let K1: keyof boolean; // let K1: "valueOf"
let K2: keyof number; // let K2: "toString" | "toFixed" | "toExponential" | ...
let K3: keyof symbol; // let K1: "valueOf"

此外 keyof 也称为输入索引类型查询,与之相对应的是索引访问类型,也称为查找类型。在语法上,它们看起来像属性或元素访问,但最终会被转换为类型:

type P1 = Person["name"];
// string
type P2 = Person["name" | "age"];
// string | number
type P3 = string["charAt"];
// (pos: number) => string
type P4 = string[]["push"];
// (...items: string[]) => number
type P5 = string[][0];
// string

作用

function prop(obj: object, key: string) {
return obj[key];
}

在上面代码中,为了避免调用 prop 函数时传入错误的参数类型,我们为 obj 和 key 参数设置了类型,分别为 {}string 类型。然而,事情并没有那么简单。针对上述的代码,TypeScript 编译器会输出以下错误信息:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.

原因:元素隐式地拥有 any 类型,因为 string 类型不能被用于索引 {} 类型。

function prop<T extends object, K extends keyof T>(obj: T, key: K) {
return obj[key];
}

在以上代码中,我们使用了 TypeScript 的泛型和泛型约束。首先定义了 T 类型并使用 extends 关键字约束该类型必须是 object 类型的子类型,然后使用 keyof 操作符获取 T 类型的所有键,其返回类型是联合类型,最后利用 extends 关键字约束 K 类型必须为 keyof T 联合类型的子类型。

type Todo = {
id: number;
text: string;
done: boolean;
}
const todo: Todo = {
id: 1,
text: "Learn TypeScript keyof",
done: false
}
function prop<T extends object, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
const id = prop(todo, "id"); // const id: number
const text = prop(todo, "text"); // const text: string
const done = prop(todo, "done"); // const done: boolean

如果访问todo对象中不存在的属性,那么就会报错

const date = prop(todo, "date");
//Argument of type '"date"' is not assignable to parameter of type '"id" | "text" | "done"'.

typeof与keyof的结合

const COLORS = {
red: 'red',
blue: 'blue'
}
// 首先通过typeof操作符获取color变量的类型,然后通过keyof操作符获取该类型的所有键,
// 即字符串字面量联合类型 'red' | 'blue',取自于k
type Colors = keyof typeof COLORS
let color: Colors;
color = 'red' // Ok
color = 'blue' // Ok
// Type '"yellow"' is not assignable to type '"red" | "blue"'.
color = 'yellow' // Error

T[K] 索引访问

interface Eg1 {
name: string,
readonly age: number,
}
// string
type V1 = Eg1['name']
// string | number
type V2 = Eg1['name' | 'age']
// any
type V2 = Eg1['name' | 'age2222']
// string | number
type V3 = Eg1[keyof Eg1]

T[keyof T]的方式,可以获取到T所有key的类型组成的联合类型;

T[keyof K]的方式,获取到的是T中的key且同时存在于K时的类型组成的联合类型;

注意:如果[]中的key有不存在T中的,则是any;因为ts也不知道该key最终是什么类型,所以是any;且也会报错

& 交叉类型注意点

交叉类型取的多个类型的并集,但是如果相同key但是类型不同,则该keynever

interface Eg1 {
name:string,
age:number
}
interface Eg2 {
name:string,
age:string,
color: string,
}

以上两个接口定义的name,age属性名是相同的,但是属性的类型并不相同

type T = Eg1 & Eg2

T的类型为 {name: string; age: never; color: string}

注意,age因为Eg1和Eg2中的类型不一致,所以交叉后age的类型是never

最后

以上就是危机钢铁侠为你收集整理的Ts keyof的全部内容,希望文章能够帮你解决Ts keyof所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部