类型学习
值到类型转换
// 数值
const type = ["primary", "secondary"] as const
type buttonType = typeof type[number]
// type buttonType = "primary" | "secondary"
type IButton = { [key in buttonType]: string }
/* type IButton = {
primary: string;
secondary: string;
} */
常见场景:
- 创建组件样式映射(如本例)。
- 实现枚举到值的映射。
- 从配置数组自动生成类型定义。
优势
- 类型安全:任何不在 type 数组中的键都会导致编译错误。
- 可维护性:修改 type 数组时,类型系统会自动更新所有依赖。
- 代码简洁:避免手动重复书写类型定义。
类型条件
通过 extends 关键字加三目运算符来实现类型条件判断。
// 类型定义
interface Human {
creative: true;
name?: string;
}
interface Animal {
species: string;
}
type Creature = Human | Animal;
// 使用示例
const creature1 = { creative: true, name: 'Alice' };
const creature2 = { species: 'cat' };
// 类型判断
type species1 = typeof creature1 extends {creative: boolean} ? Human : Animal
// type species1 = Human
type species2 = typeof creature2 extends {creative: boolean} ? Human : Animal
// type species2 = Animal
泛型
泛型是指在定义函数、接口或类时,不指定具体的类型,而是在使用时再指定类型。
// 泛型定义
type creatureType<T> = T extends {creative: boolean} ? Human : Animal
// 类型判断
type species1 = creatureType<typeof creature1>
// type species1 = Human
type species2 = creatureType<typeof creature2>
// type species2 = Animal
剔除方法的使用
type NonFunctionPropertyNames < T >= {
[K in keyof T]: T[K] extends Function ? never: K;
}[keyof T];
// {}[keyof T] 是获取对象值的类型,never就不显示代表剔除方法,其他的就是值的类型。
type NonFunctionProperties < T >= Pick<T, NonFunctionPropertyNames<T>>;
// 调用pick方法,第一个参数是对象,第二个参数是类型。
// 获取对象中不是方法的属性
class UserService {
id: number = 1;
name: string = "John";
save(): void {}
delete (): void {}
}
type remain = NonFunctionPropertyNames<UserService>
// type remain = "id" | "name"
type UserData = NonFunctionProperties<UserService>;
// UserData is: { id: number; name: string }
// 方法被自动过滤掉了!
类的定义(UserService) 既是值(类的构造函数),也是类型(类的实例结构),因此泛型中的T可以直接传入类(UserService)
在类型工具的上下文中(如 type 定义、泛型约束),类名默认指其类型。
如果你想引用类的构造函数类型,需要显式使用 typeof UserService。
is关键字实现类型守卫
缩小类型范围
//类型定义
type admin = {
name: string;
age: number;
token: 'admin'
}
type normal = {
name: string;
age: number;
id: 'normal'
}
// 使用示例
const user:any = {
name: '123',
age: 123,
id: 'normal'
}
// 类型守卫
function isAdmin (user: admin | normal): user is admin {
return 'token' in user
}
//它的作用是告诉编译器:“当这个函数返回 true 时,传入的参数类型是我指定的类型”。
//使用
if(isAdmin(user)){
// 缩小了user类型范围
user
// const user: admin
console.log(user.token)
}
在 TypeScript 中,is 关键字是类型守卫的核心语法,它的作用是:
- 在运行时检查值的类型。
- 在编译时为 TypeScript 提供类型信息,从而实现类型安全。
通过 is,可以编写更精确、更安全的类型检查逻辑,让 TypeScript 编译器理解并应用类型缩小。
infer推断
窥探类型内部结构
// 函数返回值推断
type myReturn<T> = T extends () => infer R ? R : never;
type exampleReturn = myReturn<() => Promise<string>>
// type exampleReturn = Promise<string>
多个变量推断
type functioninfer<T> = T extens (first: infer A,second: infer B) => infer R ? {
args: [A ,B],
return: R
} : never
提取数组元素
type ArrayEle<T> = T extends (infer R)[] ? R : never