交叉类型
- &
```typescript
const mergeFunc =
(arg1: T, arg2: U): T & U => { const res = {} as T & U res = Object.assign(arg1, arg2) return res }
// 利用 mergeFun 我们可以合并两个对象为一个对象 mergeFunc({a: ‘a’}, {b: ‘b’}) // 结果为 {a: ‘a’, b: ‘b’}
<a name="Isjki"></a>### 联合类型- 类型是多种类型中的任意一个,符号 |```typescriptconst data: string | number // data 既可以是 string 又可以是 number
类型保护
当一个函数可能返回多种情况值类型,这时候我们需要类型保护,不然ts不知道该函数的返回值类型是什么
typeof
使用 typeof 类型保护 (string/number/boolean/symbol) 中的一种 ```typescript const func: () => string | number const data = func() //此时data 可能是string 也可能是 number
//使用 typeof 类型保护 (string/number/boolean/symbol) 中的一种
if(typeof data === ‘string’) { // data.length } else { // data.toFixed() }
- typeof 用在TypeScript 中,含义跟JavaScript中不同。不再简单的表示 跟在它后面的值的类型- let instance : ClassA; 表示的是 instance 的类型是ClassA的实例- let classA: typeof ClassA; 表示的是 classA 的类型就是 ClassA<a name="NS0AR"></a>#### instranceof- 判断实例是由哪个类创建的```typescriptclass A {public age: numberconstructor() {}}class B {public name: stringconstructor() {}}const data : A | B // 简单表示 data 是 A B 类当中的某一个实例if(data instranceof A) {//...} else {//...}
类型别名 type
- 引用其他类型使用(为其他类型起个新的名字使用)
- 抽象代码使用 ```typescript type TypeString = string const str: TypeString
//在泛型中使用
type PositionType
const p2: PositionType
//树形
type Childs
const data: Childs
// 固定值类型 type Direction = ‘north’ | ‘east’ | ‘south’ | ‘west’
const func = (direction: Direction) => { //direction的值只能是 ‘north’ | ‘east’ | ‘south’ | ‘west’ 中的一个 }
type Count = 10
interface App { name: string, pod: Count }
<a name="hHbyF"></a>### 可辨识联合- 具有普通的单例类型属性- 一个类型中包括了多种类型的联合```typescript//①首先我们先mock几个具有普通的单例类型属性的接口interface Square {kind: 'square';size: number}interface Rectangle {kind: 'rectangle';height: number;weight: number;}interface Circle {kind: 'circle';radius: number;}//②使用类型别名 type 声明一个联合类型,包括以上3中类型type Shape = Square | Rectangle | Circleconst assertNever = (v: never): never => { // never 的一般使用throw new Error(`Unexpected .....${v}`)}const getArea = (shape: Shape) => {switch(shape.kind) {case 'square':return shape.size * shape.sizecase 'rectangle':return shape.height * shape.heightcase 'circle':return Math.PI * shape.radius ** 2 // ES7语法 ** 2 表示 平法default: return assertNever(shape)}}
this类型使用
链式调用
在class 类中的 this 代表该类的实例对象 ```typescript class Counter { constructor(public count: number) { } public add(v: number) { this.count += v return this }
public subtract(v: number) { this.count -= v return this } }
const counter: Counter = new Counter(10) // 链式调用 counter.add(1).subtract(4)
在子类中也能实现链式调用```typescriptclass PowCounter extends Counter {constructor(public count: number =0 ) {super(count)}public pow(v: number){this.count = this.count ** vreturn this}}const powCounter: PowCounter = new PowCounter(2)// 链式调用powCounter.pow(2).add(4).subtract(1)
索引属性
keyof
连接一个类型,返回该类型所有属性的联合类型
interface A {name: string;age: number}//此时data 的值只能是 name 或者 ageconst data: keyof A === const data: string | number
泛型中使用,获取一个对象属性的值
const getValue = <T, K extends keyof T>(obj: T, names: K[]): Array<T[K]> => {return names.map(n => obj[n])}// Array<T[K]> === T[K][]const mockObj = {name: 'zxc',age: 18}const value: (string | number)[] = getValue(mockObj, ['name', 'age'])
索引访问操作符
比如: 把一个类型转换成每个字段都是只读的或者可选的 ```typescript interface App { name: string; status: number; desc: string; }
// 需要把App 接口(或者 更多接口)的属性修改为只读或者可选
type ReadonlyType
type ReadonlyApp = ReadonlyType
//这样我们定义的对象用ReadonlyApp 类型,它的属性就是只读以及可选 const app: ReadonlyApp = { name: ‘app’, status: 1, desc: ‘app desc’; }
- 其实 ts 中已经封装了 类似于上面思想的 type 类,即 pick```typescript// ts 封装的 Pick 类type Pick<T, K extends keyof T> = {[P in K]: T[P]}// 使用一下 pickconst pick = <T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> => {const res: any = {}keys.map(key => {res[key] = obj[key]})return res}// 我们测试一下const mockData = {name: 'zxc',age: 18,addr: 'hangzhou'}console.log(pick(mockData, ['name', 'age']))// { name: 'zxc', age: 18 }console.log(pick(mockData, ['name', 'addr']))// { name: 'zxc', addr: 'hangzhou'}
- Record— 把一个对象属性的值转换成其他类型
```typescript
// ts 封装的 Record 类
type Record
= {
}
//我们看一下 Record 类的用法
const mapObject =
const mockData = { a: ‘hello’, b: ‘world’, c: ‘str’ }
const newObj = mapObject(mockData, (s) => s.length) console.log(newObj) // { a: 5, b: 5, c: 3 }
**我们使用映射类型 对一个对象进行加工操作后,我们也可以进行拆包操作(我觉得叫还原更贴切,即 封装/还原)**```typescripttype Proxy<T> = {get(): T;set(value: T): void; // 之前说过 存取器中 set函数没有返回值}type Proxify<T> = {[P in keyof T]: Proxy<T[P]> // 把遍历的每一个值都放进去}const proxify = <T>(obj: T): Proxify<T> => {const res = {} as Proxify<T>for(const key in obj){res[key] = {get:() => obj[key],set:(value) => obj[key = value}}return res}// 我们测试一下const mockData = {name: 'zxc',age: 18}const newobj = proxify(mockData)
打印结果:对象的每个属性都具备了 get 和 set 方法
我们再将对象拆包(还原)
const unProxify = <T>(data: Proxify<T>): T => {const res = {} as Tfor(const k in data){res[key] = data[key].get()}return res}let originalObj = unProxify(newobj)console.log(originalObj) // 得到原始对象 {name : 'zxc', age: 18 }
元组和数组上的映射类型
看一下promise 的使用
type MapToPromise<T> = {[K in typeof T]: Promise<T[K]> //定义返回的值都是Promise}type Tuple = [number, string, boolean]type PromiseTuple: MapToPromise<Tuple>const data: PromiseTuple = [new Promise((resolve, reject) => resolve(1)),new Promise((resolve, reject) => resolve('a')),new Promise((resolve, reject) => resolve(false)),]// 注意 data 的类型即const data: [Promise<number>, Promise<string>, Promise<boolean>]
unknown类型
任何类型都可以复制给unknown类型
const value: unknownvalue = 1value = 'a'
如果没有类型断言或者基于控制流的类型细化,unknown不可以赋值给其他类型,只能赋值给any或者它本
const value: unknownconst value1: stringvalue1 = value // 是错误的
如果没有类型断言或者基于控制流的类型细化,不能在它身上进行任何操作
const value: unknownvalue++ // 是错误的
unknown与其他类型组成的交叉类型,最后都等于其他类型
type A = string & unknownconst data: A // data 的类型为string
unknown与其他类型除了(any)组成的联合类型,都等于unknown类型
type A = string | unknown // A 为 unknowntype B = any | unknown // B 为 any (any 特殊)
never 类型是 unknown 的子类型
keyof unknown 等于类型 never
type A = keyof unknown // A 类型为 never
只能对 unknown 进行等或者不等操作,不能进行其他的操作
const value: unknown = 1const value1: unknown = 2value !== value1
使用映射类型时,如果遍历的是unknown类型,则不会映射任何属性 ```typescript type A
= {
}
type B = A
<a name="kEjhj"></a>### 条件类型- T extends U ? X : Y```typescripttype A<T> = T extends string ? string : numberconst data: A<10> // data就是一个number 类型的值// 灵活使用type A<T> =T extends string ? string :T extends number ? number :T extends boolean ? boolean :T extends undefined ? undefined :T extends () => void ? () => void :objecttype B = A<() => void> // 此时B类型就是一个函数类型type C = A<string[]> // 此时C类型就是一个 object 类型type D = A<(() => void) | string[]> // 此时D类型就是一个 函数类型 和 object 类型组成的联合类型// 实际应用type Diff<T, U> = T extends U ? never : Ttype A = Diff<string | number | boolean, undefined | number> // A类型就是 string | boolean
注意:ts 2.8版本以上已封装了类似 Diff 类型的用法—-Exclude
type A = Exclude<'a' | 'b' | 'c', 'a' | 'b'> // A 类型就是 c 类型// 从前半部分挑出 后半部分没有的类型
类型推断
infer(条件类型的类型推断)
//不使用 infertype A<T> = T extends any[] ? T[number] : T // 是数组的话返回数组中元素的类型否则返回它本身类型type B = A<string[]> // B 就是 string 类型,因为数组的元素是 string 类型type B = A<string> // B 也是 string 类型使用 infertype A<T> = T extends Array<infer U> ? U : Ttype B = A<string[]> // B 就是 string 类型,因为数组的元素是 string 类型type B = A<string> // B 也是 string 类型
Extract
从T 中找出可以 赋值 给U 的(联合)类型
type A = Extract<'a' | 'b' | 'c', 'c'> // A 就是c 类型
NonNullable
从 T 中除去 null 和 undefined 类型
// A === string | numbertype A = NonNullable<string | number | null | undefined >
ReturnType
返回一个函数返回值的类型
type A = ReturnType<() => string> // A === string
InstanceType
返回一个构造函数实例的类型
- 只能判断类型为构造函数 以及 any ```typescript class AClass { contructor() {} }
type B = InstanceType
