Skip to content

Commit 00cf9a5

Browse files
authored
Update typeScript.md
1 parent 86a4748 commit 00cf9a5

File tree

1 file changed

+237
-17
lines changed

1 file changed

+237
-17
lines changed

docs/es6/typeScript.md

+237-17
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,173 @@
1-
### 概述
1+
### 初次见面
2+
官方对其只用了一句话来描述
3+
> TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. Any browser. Any host. Any OS. Open source.
4+
5+
大致意思为,TypeScript 是开源的,TypeScript 是 JavaScript 的类型的**超集**,它可以编译成纯 JavaScript。编译出来的 JavaScript 可以运行在任何浏览器上。TypeScript 编译工具可以运行在任何服务器和任何系统上
6+
7+
* 问题1: 什么是超集
8+
9+
**超集是集合论的术语**
10+
说到超集,不得不说另一个,子集,怎么理解这两个概念呢,举个例子
11+
12+
如果一个集合A里面的的所有元素集合B里面都存在,那么我们可以理解集合A是集合B的超集,反之集合B为集合A的子集
13+
14+
现在我们就能理解为 `Typescript` 里包含了 `Javascript` 的所有特性,这也意味着我们可以将`.js`后缀直接命名为`.ts`文件跑到`TypeScript`的编绎系统中
15+
16+
### Typescript 解决了什么问题
17+
18+
**一个事物的诞生一定会有其存在的价值**
19+
20+
那么 `Typescript` 的价值是什么呢?
21+
22+
回答这个问题之前,我们有必要先来了解一下 `Typescript` 的工作理念
23+
24+
本质上是在 `JavaScript` 上增加一套**静态类型系统**(编译时进行类型分析),强调静态类型系统是为了和运行时的类型检查机制做区分,`TypeScript` 的代码最终会被编译为 `JavaScript`
25+
26+
我们再回到问题本身,缩小一下范围,`Typescript` 创造的价值大部分是在开发时体现的(编译时),而非运行时,如
27+
28+
- 强大的编辑器智能提示 (研发效率,开发体验)
29+
- 代码可读性增强 (团队协作,开发体验)
30+
- 编译时类型检查 (业务稳健,前端项目中Top10 的错误类型低级的类型错误占比达到70%)
31+
32+
### 正文
33+
34+
本篇文章作为 `Vue3` 源码系列前置篇章之一,`Typescript` 的科普文,主要目的为了大家在面对 `Vue3` 源码时不会显得那么不知所措,下来将介绍一些 `Typescript` 的基本使用
235

336
### 变量申明
37+
38+
#### 基本类型
439
```js
40+
let isDone: boolean = false
541
let num: number = 1
6-
let str: string = 'hello'
42+
let str: string = 'vue3js.cn'
43+
let arr: number[] = [1, 2, 3]
44+
let arr2: Array<number> = [1, 2, 3] // 泛型数组
45+
let obj: Object = {}
46+
let u: undefined = undefined;
47+
let n: null = null;
748
```
849

9-
### 函数参数类型与返回值类型
50+
#### 类型补充
51+
52+
- 枚举 `Enum`
53+
54+
使用枚举类型可以为一组数值赋予友好的名字
1055
```js
11-
function sum(a: number, b: number): number {
12-
return a + b
56+
enum LogLevel {
57+
info = 'info',
58+
warn = 'warn',
59+
error = 'error',
1360
}
1461
```
15-
### 复合元素类型
62+
63+
- 元组 `Tuple`
64+
65+
允许数组各元素的类型不必相同。 比如,你可以定义一对值分别为 string和number类型的元组
66+
67+
```js
68+
// Declare a tuple type
69+
let x: [string, number];
70+
// Initialize it
71+
x = ['hello', 10]; // OK
72+
// Initialize it incorrectly
73+
x = [10, 'hello']; // Error
74+
```
75+
76+
- 任意值 `Any`
77+
78+
表示任意类型,通常用于不确定内容的类型,比如来自用户输入或第三方代码库
79+
1680
```js
17-
let arr: Array<number> = [1, 2, 3]
18-
let set: Set<number> = new Set([1, 2, 2])
19-
let map: Map<string, number> = new Map([['key1', 1], ['key2', 2]])
81+
let notSure: any = 4;
82+
notSure = "maybe a string instead";
83+
notSure = false; // okay, definitely a boolean
2084
```
21-
### 接口类型
85+
- 空值 `Void`
86+
87+
与 any 相反,通常用于函数,表示没有返回值
88+
89+
```js
90+
function warnUser(): void {
91+
console.log("This is my warning message");
92+
}
93+
```
94+
95+
- 接口 `interface`
96+
97+
类型契约,跟我们平常调服务端接口要先定义字段一个理
98+
99+
如下例子 point 跟 Point 类型必须一致,多一个少一个也是不被允许的
22100
```js
23101
interface Point {
24102
x: number
25103
y: number
104+
z?: number
105+
readonly l: number
26106
}
27-
const point: Point = { x: 10, y: 20 }
107+
const point: Point = { x: 10, y: 20, z: 30, l: 40 }
108+
const point2: Point = { x: '10', y: 20, z: 30, l: 40 } // Error
109+
const point3: Point = { x: 10, y: 20, z: 30 } // Error
110+
const point4: Point = { x: 10, y: 20, z: 30, l: 40, m: 50 } // Error
111+
28112
```
29-
### 类型别名
113+
114+
可选与只读 ? 表示可选参, readonly 表示只读
115+
116+
```js
117+
const point5: Point = { x: 10, y: 20, l: 40 } // 正常
118+
point5.l = 50 // error
119+
```
120+
121+
### 函数参数类型与返回值类型
122+
123+
```js
124+
function sum(a: number, b: number): number {
125+
return a + b
126+
}
127+
```
128+
129+
配合 `interface` 使用
130+
30131
```js
31-
type mathfunc = (a: number, b: number) => number
32-
const product: mathfunc = (a, b) => a * b
132+
interface Point {
133+
x: number
134+
y: number
135+
}
136+
137+
function sum({ x, y}: Point): number {
138+
return x + y
139+
}
140+
141+
sum({x:1, y:2}) // 3
33142
```
34143

35144
### 泛型
36-
泛型的意义在于函数的重用性,我们希望组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型
145+
泛型的意义在于函数的重用性,设计原则希望组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型
37146

38-
**为什么不用`any`呢?**
147+
* 比如
148+
149+
根据业务最初的设计函数 `identity` 入参为`String`
150+
```js
151+
function identity(arg: String){
152+
return arg
153+
}
154+
console.log(identity('100'))
155+
```
156+
157+
业务迭代过程参数需要支持 `Number`
158+
```js
159+
function identity(arg: String){
160+
return arg
161+
}
162+
console.log(identity(100)) // Argument of type '100' is not assignable to parameter of type 'String'.
163+
```
164+
165+
#### **为什么不用`any`呢?**
39166

40167
使用 `any` 会丢失掉一些信息,我们无法确定返回值是什么类型
41168
泛型可以保证入参跟返回值是相同类型的,它是一种特殊的变量,只用于表示类型而不是值
42169

43-
语法 `<T>(arg:T):T` 其中`T`为自定义变量,能前后对应就行
170+
语法 `<T>(arg:T):T` 其中`T`为自定义变量
44171

45172
```js
46173
const hello : string = "Hello vue!"
@@ -77,4 +204,97 @@ console.log(say(1)) // Argument of type '1' is not assignable to parameter of t
77204
console.log(say({value: 'hello vue!', length: 10})) // { value: 'hello vue!', length: 10 }
78205
```
79206

207+
### 义叉类型
208+
209+
交叉类型(Intersection Types),将多个类型合并为一个类型
210+
211+
```js
212+
interface foo {
213+
x: number
214+
}
215+
interface bar {
216+
b: number
217+
}
218+
type intersection = foo & bar
219+
const result: intersection = {
220+
x: 10,
221+
b: 20
222+
}
223+
const result1: intersection = {
224+
x: 10
225+
} // error
226+
```
227+
228+
### 联合类型
229+
230+
交叉类型(Union Types),表示一个值可以是几种类型之一。 我们用竖线 | 分隔每个类型,所以 number | string | boolean表示一个值可以是 number, string,或 boolean
231+
232+
```js
233+
type arg = string | number | boolean
234+
const foo = (arg: arg):any =>{
235+
console.log(arg)
236+
}
237+
foo(1)
238+
foo('2')
239+
foo(true)
240+
```
241+
242+
### 函数重载
243+
244+
函数重载(Function Overloading), 允许创建数项名称相同但输入输出类型或个数不同的子程序,可以简单理解为一个函数可以执行多项任务的能力
245+
246+
例我们有一个`add`函数,它可以接收`string`类型的参数进行拼接,也可以接收`number`类型的参数进行相加
247+
248+
```js
249+
function add (arg1: string, arg2: string): string
250+
function add (arg1: number, arg2: number): number
251+
252+
// 实现
253+
function add <T,U>(arg1: T, arg2: U) {
254+
// 在实现上我们要注意严格判断两个参数的类型是否相等,而不能简单的写一个 arg1 + arg2
255+
if (typeof arg1 === 'string' && typeof arg2 === 'string') {
256+
return arg1 + arg2
257+
} else if (typeof arg1 === 'number' && typeof arg2 === 'number') {
258+
return arg1 + arg2
259+
}
260+
}
261+
262+
add(1, 2) // 3
263+
add('1','2') //'12'
264+
```
265+
266+
### 总结
267+
268+
通过本篇文章,相信大家对`Typescript`不会再感到陌生了
269+
270+
下面我们来看看在`Vue`源码`Typescript`是如何书写的,这里我们以`defineComponent`函数为例,大家可以通过这个实例,再结合文章的内容,去理解,加深`Typescript`的认识
271+
272+
```js
273+
// overload 1: direct setup function
274+
export function defineComponent<Props, RawBindings = object>(
275+
setup: (
276+
props: Readonly<Props>,
277+
ctx: SetupContext
278+
) => RawBindings | RenderFunction
279+
): {
280+
new (): ComponentPublicInstance<
281+
Props,
282+
RawBindings,
283+
{},
284+
{},
285+
{},
286+
// public props
287+
VNodeProps & Props
288+
>
289+
} & FunctionalComponent<Props>
290+
291+
// defineComponent一共有四个重载,这里省略三个
292+
293+
// implementation, close to no-op
294+
export function defineComponent(options: unknown) {
295+
return isFunction(options) ? { setup: options } : options
296+
}
297+
298+
```
299+
80300

0 commit comments

Comments
 (0)