1 /** 2 * @name sfxATypes 3 * @author shenyc 4 * @date 2021-08-09 5 * @copyright Copy right (c) shenyc (shenyczz@163.com). 6 * All rights reserved. 7 * @remark The Advance type in typeScript 8 * 9 ******************************************************************************/ 10 11 // 避免把 TypeScript 写成 AnyScript: 12 // 当应用越来越复杂,我们很容易把一些变量设置为 any 类型,TypeScript 写着写着也就成了 AnyScript。 13 /** 14 * 1、避免把 TypeScript 写成 AnyScript: 15 * 当应用越来越复杂,我们很容易把一些变量设置为 any 类型,TypeScript 写着写着也就成了 AnyScript。 16 */ 17 18 /** 19 * 基础类型 20 */ 21 let b: Boolean = true; 22 let s: String = '' 23 let n: Number = 0; 24 let e: null = null; 25 let u: undefined = undefined; 26 let o: Object = {}; 27 28 /** 29 * 数组 30 */ 31 let as: String[] = []; 32 let ag: Array<Number> = [1, 2, 3]; 33 let ai: Int16Array = new Int16Array(); 34 35 /** 36 * 接口 37 */ 38 interface IPerson { 39 age: number; 40 name: string; 41 42 } 43 44 /** 45 * 类 46 */ 47 class Person implements IPerson { 48 age: number; 49 name: string; 50 } 51 class Famer extends Person { } 52 53 /** 54 * 泛型 55 */ 56 function Foo<T>() { 57 // console.log(typeof T); 58 } 59 60 /** 61 * 高级类型 - 交叉类型(&) 62 */ 63 interface A { id: number; }; 64 interface B { name: string; }; 65 let tab: A & B = { 66 id: 10, 67 name: "123" 68 }; 69 70 /** 71 * 高级类型 - 联合类型(|) 72 */ 73 let tu: Boolean | Number | String; 74 tu = true; 75 tu = 1; 76 tu = "123"; 77 78 /** 79 * 高级类型 - 类型别名(type) 80 */ 81 type StringLike = String | String[]; 82 let talias: StringLike = undefined; 83 talias = '0'; 84 talias = ['', '']; 85 86 /** 87 * 类型索引(keyof) 88 */ 89 interface Button { 90 type: string; 91 text: string; 92 } 93 94 type ButtonKeys = keyof Button; 95 96 97 /** 98 * 类型约束(extends) 99 */ 100 function print<T extends String>(arg: T): void { 101 console.log(arg); 102 } 103 104 // extends 经常与 keyof 一起使用, 105 // 例如我们有一个方法专门用来获取对象的值,但是这个对象并不确定, 106 // 我们就可以使用 extends 和 keyof 进行约束。 107 function getValue<T, K extends keyof T>(obj: T, key: K) { 108 return obj[key] 109 } 110 111 const obj = { flag: 1 } 112 const a = getValue(obj, 'flag') 113 114 /** 115 * 类型映射(in) 116 * 117 * in 关键词的作用主要是做类型的映射,遍历已有接口的 key 或者是遍历联合类型。 118 * 下面使用内置的泛型接口 Readonly 来举例。 119 */ 120 121 interface Obj { 122 a: string 123 b: string 124 } 125 126 type ReadOnlyObj = Readonly<Obj> 127 128 /** 129 * 条件类型(U ? X : Y) 130 */ 131 type CommonKeys = Extract<keyof Person, keyof Famer> 132 133 134 /** 135 * 工具泛型 136 * 137 * TypesScript 中内置了很多工具泛型,前面介绍过 Readonly、Extract 这两种, 138 * 内置的泛型在 TypeScript 内置的 lib.es5.d.ts 中都有定义,所以不需要任何依赖都是可以直接使用的。 139 * 下面看看一些经常使用的工具泛型吧。 140 */ 141 142 /** 143 * 工具泛型 - Partial 144 * 用于将一个接口的所有属性设置为可选状态 145 */ 146 interface IMan { 147 age: number; 148 name: string; 149 } 150 151 let one: IMan = { 152 // 必须设置所有属性 153 age: 0, 154 name: "one" 155 }; 156 157 let two: Partial<IMan> = { 158 // 所有属性都是可选属性 159 }; 160 161 162 /** 163 * 工具泛型 - Required 164 * * Required 的作用刚好与 Partial 相反,就是将接口中所有可选的属性改为必须的 165 */ 166 interface C { 167 x?: number; 168 s?: string; 169 } 170 171 let cobj1: C = {}; 172 let cobj2: Required<C> = { x: 0, s: '', }; 173 174 /** 175 * Record 176 * Record 接受两个类型变量,Record 生成的类型具有类型 K 中存在的属性,值为类型 T。 177 * 这里有一个比较疑惑的点就是给类型 K 加一个类型约束,extends keyof any,我们可以先看看 keyof any 是个什么东西。 178 */ 179 interface Food { 180 id: string 181 name: string 182 price: string 183 image: string 184 } 185 const goodsMap: Record<string, Food> = {}; 186 const goodsList: Food[] = []; 187 188 goodsList.forEach(food => { 189 goodsMap[food.name] = food; 190 }) 191 192 193 /** 194 * Pick 195 * Pick 主要用于提取接口的某几个属性。 196 */ 197 interface Todo { 198 title: string 199 completed: boolean 200 description: string 201 } 202 type TodoPreview = Pick<Todo, "title" | "completed">; 203 204 const todo: TodoPreview = { 205 title: 'Clean room', 206 completed: false 207 } 208 209 /** 210 * Exclude 211 * Exclude 的作用与之前介绍过的 Extract 刚好相反, 如果 T 中的类型在 U 不存在,则返回,否则抛弃。 212 */ 213 interface Teacher { 214 name: string 215 age: number 216 email: string 217 salary: number 218 } 219 220 interface Student { 221 name: string 222 age: number 223 email: string 224 grade: number 225 } 226 227 type ExcludeKeys = Exclude<keyof Teacher, keyof Student> 228 // => salary, 取出的是 Teacher 在 Student 中不存在的 salary。 229 230 /** 231 * Omit 232 * Omit 的作用刚好和 Pick 相反 233 * 先通过 Exclude<keyof T, K> 先取出类型 T 中存在,但是 K 不存在的属性, 234 * 然后再由这些属性构造一个新的类型。 235 * 还是通过前面的 Todo 案例来说,TodoPreview 类型只需要排除接口的 description 属性即可,写法上比之前 Pick 精简了一些。 236 */ 237 interface Something { 238 id: number; 239 name: string; 240 description: string; 241 } 242 type SomethingOmit = Omit<Something, "description"> 243 // => SomethingOmit { id: number; name: string; } 244 245 246 /** 247 * 最后是变量的类型 248 */ 249 let x: string = '123' 250 let xtype = typeof x;