类型层级
infer
infer是inference的缩写,用来在条件类型中提取类型的某些信息。 infer只能在函数类型结构和条件类型中使用,例如
type FunctionReturnType<T extends Func> = T extends ( ...args: any[] ) => infer R ? R : never;
索引签名类型
在接口或者类型别名中,声明一个键值类型一致的类型结构
interface stringTypes {
[key: string]: string // 类型结构变量中只能声明字符串类型的键
}
索引签名类型里具体的键值类型需要符合索引签名类型的声明
interface stringtTypes {
prop: number; //类型“number”的属性“prop”不能赋给“string”索引类型“string”
[key: string]: string
}
由于在javascript中,会将数字索引访问转换为字符串索引访问,所以在字符串索引签名中可以声明数字类型和symbol的键
interface stringtTypes {
'age': '1',
1: 'age',
[key: string]: string
}
keyof 索引类型查询
关键字,用于获取一个类型的所有键的联合类型
interface userInfo {
name: string;
age: number;
1:2
}
type key = keyof userInfo; // 'name' | 'age' | 1 数字类型的键名不会转换为字符串类型字面量
//操作类
class User {
name: string = 'name1'
}
let sname: keyof User = 'name'
泛型中keyof的使用
interface UserInfo {
name: string;
age: number;
}
class User {
constructor(private user: UserInfo) {}
// getInfo(key: string) {
// if (key === 'name' || key === 'age') {
// return this.user[key]
// }
// }
// key值不做校验,没有限制任意传值,导致程序报错;加上if校验,传入name和age以外的值,程序只会返回undefined
getInfo<T extends keyof UserInfo>(key: T): UserInfo[T] {
return this.user[key];
}
// T extends keyof UserInfo 限定参数范围 name,age
// key:T 类中的属性 (name,age)
// UserInfo[T] 返回对象中的属性值
}
索引类型访问
通过键的字面量类型访问键对应的键值类型
interface numberTypes {
[key: string]: number
prop: number
}
type propType = numberTypes[string] // number 未定义索引签名类型不能使用原始类型访问
type numbers = numberTypes['prop'] // number
映射类型
in关键字 基于键名映射到键值类型
type example<T> = {
[K in keyof T]: T[K]
}
type stringify<T> = {
[K in keyof T]: string
}
interface user {
name: string;
age: number;
prop: () => void
}
type stringifyUser = stringify<user>
// 等价于
// interface stringifyUser {
// name: string;
// age: string;
// prop: void
// }
模板字面量类型
以字符串字面量类型为基础,通过联合类型扩展成多个字符串,只能在类型定义中使用,模板字面量类型中的变量只能说原始类型string、number、bigint、boolean、null、undefined或这些类型的联合类型。
- 基本语法
type actions = 'add' | 'remove';
type property = 'name' | 'age';
type result = `${actions}${Capitalize<property>}`; // type result = addName | addAge | removeName | removeAge
- 类型推断
type Direction = 'left' | 'right' | 'top' | 'bottom';
type InferRoot<T> = T extends `${infer K}${Capitalize<Direction>}` ? K : T;
type Result1 = InferRoot<'marginRight'>; // type Result1 = 'margin';
type Result2 = InferRoot<'paddingLeft'>; // type Result2 = 'padding';