索引类型
- 实现一个pick函数,函数可以从对象上取出指定的属性,在js中应该是这样
在TS中实现pick函数, ```typescript // 第一版 interface Obj {function pick(o, names) {
return names.map(o => o[n])
}
// 从user中对象中取出id
const user = {
username: 'garen',
id: '123456',
token: 'abcefg',
role: 'admin'
}
const id = pick(user, ['id'])
console.log(id) ;// 123456
[key: string]: any;
}
function pick(o: Obj, names: string[]) { return names.map(o => o[n]) } // 类型定义不严谨, 参数names的成员应该是参数o的属性, // pick函数的返回值是any[], 应该是所取属性值的联合类型
如何定义更精准的类型,必须使用索引类型查询操作符和索引访问操作符
<a name="094LX"></a>
## 索引类型查询操作符
keyof, 作用于泛型T上获取泛型T上的所有public属性名构成联合类型
```typescript
class Images {
public src: string = 'xxx.xxx.com/yyy.png'
public alt: string = '百度'
public width: number = 500
}
type propNames = keyof Images; // alt|src|width
索引访问操作符
keyof 可以查询索引类型的属性名,访问类型的操作符也是通过 [] 访问, 即T[K];
上面的例子,已经取出的属性名propsNames, 然后通过类型访问的操作符获取值的类型
class Images {
public src: string = 'xxx.xxx.com/yyy.png'
public alt: string = '百度'
public width: number = 500
}
type propNames = keyof Images; // alt|src|width
type propTypes = Images[propNames]
有了这两个操作符,重新实现pick函数
function pick<T, K extends keyof T>(o: T, names: K[]): T[K][] {
return names.map(n => o[n])
}
const res = pick(user, ['token', 'id'])
映射类型
把user接口中的成员全部变成可选了,映射类型适用于这种场景,语法是 [ K in Keys]
K: 类型变量,依次绑定到每个属性上,对应每个属性名的类型
Keys: 字符串字面量构成的联合类型,标识一组属性名(的类型)
interface User {
username: string
id: number
token: string
avatar: string
role: string
}
type partial<T> = { [K in keyof T]?: T[K] }
type partialUser = partial<User>
小结
- 索引类型,结合泛型使用
- 索引查询操作符, keyof, K extends keyof T
- 索引访问操作符, [], T[K]
- 映射类型, [ K in Keys ], [ K in keyof T]