TypeScript 高级数据类型
Dictionary 和 NumericDictionary
Dictionary:一个对象,键是 string 类型。
NumericDictionary:一个对象,键是 number 类型。
注意:要手动实现下,通过「索引签名」+「范型」。
定义:
1 | interface Dictionary<T = any> { |
使用起来:
1 | const data2: Dictionary<number> = { |
Record
ts 原生支持,看下它的定义:
1 | type Record<K extends string | number | symbol, T> = { [P in K]: T }; |
简单来说,对于类型 Record<KEY_TYPE, VALUE_TYPE>
声明的对象,键的类型就是 KEY_TYPE,值的类型是 VALUE_TYPE。
它和直接用 interface 有啥区别? 一般 Record 可以用来做字段扩展、将值的类型转化为指定的 VALUE_TYPE、将键的类型转化为指定的 KEY_TYPE。
例子:
1 | interface Person { |
Pick
ts 原生支持:
1 | type Pick<T, K extends keyof T> = { [P in K]: T[P] }; |
作用:将某个类型指定键挑出来,组成新的类型。
例如:
1 | interface Student { |
Exclude
ts 原生支持:
1 | // 提取T包含在U中的类型 |
作用:将联合类型中的指定类型去掉。
例如:
1 | type NUMBERS = 0 | 1 | 2 | "a" | "b"; |
Extract
作用:将公有属性提取出来。
例如:
1 | type NUMBERS = 0 | 1 | 2 | "a" | "b"; |
函数相关-Parameters
作用:获取函数参数类型。
例如:
1 | function getPerson(name: string, value?: number): any {} |
函数相关-ReturnType
作用:获取函数返回类型。
例如:
1 | function getPerson(name: string, value?: number): any {} |
TypeScript 高级操作符
const 断言
特点:
- 字面量(数组、接口)类型变为 readonly
- 字面量类型不能被扩展
举例:
不使用 const 断言:
1 | const CONFIG_KEYS = ["name", "school", "country"]; |
使用 const 断言,ts 推断更精确:
1 | const CONST_CONFIG_KEYS = ["name", "school", "country"] as const; |
typoef 和 type
typeof 在 js 中,可以获得对象类型.
在 ts 中,能够配合 type 关键词,将对象类型保存在类型字面量中。
1 | const CONFIG_KEYS = ["name", "school", "country"]; |
keyof
keyof 用来获取某种类型的所有键,注意不是某个变量。
例子:假设声明了一个 json 对象,然后想获取它的所有键的类型应该怎么办?
1 | // 利用 const 断言,告诉解释器不能被扩展 |
再来一个用例,比如断言Reflect.ownKeys()
的返回结果的类型:
1 | const obj = { |
extends
基础的用法:可以用于 class 继承、interface 继承。除此之外,还用于“类型约束”。
用法 1: T extends U ? X : Y
用法:T extends U ? X : Y
。这个比较难理解,而且很常见。其实就是:如果 T 包含的类型是 U 包含的类型的 ‘子集’,那么取结果 X,否则取结果 Y。
举例:
1 | type Diff<T, U> = T extends U ? never : T; // 找出T和U的差集 |
用法 2: 范型约束
用法:<T extends Lengthwise>
。
举例:
1 | interface Lengthwise { |
如果写成 function loggingIdentity<T>(arg: T): T
,就会报错:T 上不存在 length 属性。正如所见,约束范型,传入的 arg 必须有 length 属性。
infer
作用:针对 ts 推断的类型,声明一个字面量,在extends
语句中使用。
举例:
1 | // 获得函数的返回类型 |
例子中的infer R
就是传入参数(某个函数)的返回类型,在这个表达式中,函数的返回类型被R
变量代替。
:::warning infer 使用的位置
infer 声明的这个变量只能在 true 分支中使用
:::
infer的更多内容可以参考 https://jkchao.github.io/typescript-book-chinese/tips/infer.html#一些用例 :
ReturnType
:获取函数返回类型(内置)ConstructorParameters
:获取构造函数类型(内置)InstanceType
:获取 class 类型(内置)ElementOf
:获取数组元素类型
反解 Promise
理解了 ReturnType,我写出了一个反解 Promise的 typescript 扩展类型:
1 | type UnPromiseType<T extends (...args: any) => any> = T extends ( |
使用效果:
1 | async function main(): Promise<string> { |