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。
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;