TypeScript 条件类型浅析
发布时间:2023-03-30 14:03:03 所属栏目:教程 来源:
导读:条件类型用来表达非均匀类型映射,可以根据一个条件表达式来进行类型检测,从两个类型中选出其中一个:
T extends U ? X : Y
语义类似三目运算符:若 T 是 U 的子类型,则类型为 X,否则类型为 Y。若无法确定 T
T extends U ? X : Y
语义类似三目运算符:若 T 是 U 的子类型,则类型为 X,否则类型为 Y。若无法确定 T
|
条件类型用来表达非均匀类型映射,可以根据一个条件表达式来进行类型检测,从两个类型中选出其中一个: T extends U ? X : Y 语义类似三目运算符:若 T 是 U 的子类型,则类型为 X,否则类型为 Y。若无法确定 T 是否为 U 的子类型,则类型为 X | Y。 declare function f<T extends boolean>(x: T): T extends true ? string : number const x = f(Math.random() < ) // const x: string | number const y = f(true) // const y: string const z = f(false) // const z: number 代码解释: 第 3 行,可以看到在条件不确定的情况下,得到了联合类型 string | number。 最后两行,条件确定时,得到了具体类型 string 或 number。 在条件类型 T extends U ? X : Y 中,当泛型参数 T 取值为 A | B | C 时,这个条件类型就等价于 (A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y),这就是可分配条件类型。 可分配条件类型(distributive conditional type)中被检查的类型必须是裸类型参数(naked type parameter)。裸类型表示没有被包裹(Wrapped) 的类型,(如:Array<T>、[T]、Promise<T> 等都不是裸类型),简而言之裸类型就是未经过任何其他类型修饰或包装的类型。 有了这些前置知识,我们就可以分析一下 TypeScript 内置的一些工具类型,就像在映射类型中介绍的可以通过 Partial<T>,可以在项目中直接使用。 Exclude<T, U> – 从 T 中剔除可以赋值给 U 的类型。 Extract<T, U> – 提取 T 中可以赋值给 U 的类型。 NonNullable<T> – 从 T 中剔除 null 和 undefined。 ReturnType<T> – 获取函数返回值类型。 InstanceType<T> – 获取构造函数类型的实例类型。 用第一个来举例分析: type T00 = Exclude<'a' | 'b' | 'c' | 'd', 'a' | 'c' | 'f'> // 'b' | 'd' 来看一下 Exclude<T, U> 的实现源码: /** * Exclude from T those types that are assignable to U */ type Exclude<T, U> = T extends U ? never : T; 再看一个进阶的例子,定义一种方法,可以取出接口类型中的函数类型: type FunctionPropertyNames<T> = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T] type FunctionProperties<T> = Pick<T, FunctionPropertyNames<T>> interface Part { id: number name: string subparts: Part[] firstFn: (brand: string) => void, anotherFn: (channel: string) => string } type FnNames = FunctionPropertyNames<Part> type FnProperties = FunctionProperties<Part> 代码解释: 倒数第二行,首先,遍历整个接口,然后通过条件类型判断接口的属性值的类型是否是函数类型,如果是函数类型,取其属性名。得到: type FnNames = 'firstFn' | 'anotherFn' 倒数第一行,通过上一节介绍的工具函数 Pick,拿到这个接口的所有函数类型成员集合: type FnProperties = { firstFn: (brand: string) => void anotherFn: (channel: string) => string } 学习到了本节,可以深刻的体会到 TypeScript 中的类型不单单只是简单的给变量进行标注,还可以通过各种运算,得到很多有趣的结果。 (编辑:汽车网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐
