typescript基础01
# typescript概念
TypeScript
,是 JavaScript
的超集 = Type
+ JavaScript
添加了类型支持
let age:number = 18
因为 js
的类型系统存在先天缺陷,Ts
属于静态类型的编程语言,Js
属于动态类型的编程语言
- 静态类型:编译期做类型检查
- 动态类型:执行期做类型检查
TypeScript 相比 JS 的优势
- 更早(写代码的同时)发现错误,减少找 Bug、改 Bug 时间,提升开发效率
- 程序中任何位置的代码都有代码提示,随时随地的安全感,增强了开发体验
- 强大的类型系统提升了代码的可维护性,使得重构代码更加容易
- 支持最新的 ECMAScript 语法,优先体验最新的语法,让你走在前端技术的最前沿
- TS 类型推断机制,不需要在代码中的每个地方都显示标注类型,让你在享受优势的同时,尽量降低了学习负担
工具包
typescript
tsc xxx.ts
可以转换为js
# 常用类型
let age:number = 18
:type
类型注解,为变量添加类型约束
约定了什么类型,只能给变量赋值该类型的值,否则会报错
js
原有类型(原始类型、对象类型:数组、对象、函数等)ts
新增类型(联合类型、自定义类型、接口、元组、字面量类型、枚举、void、any等...)
# 原有类型
# 原始类型
- number
- string
- boolean
- null
- undefined
- symbol
let age: number = 18
let myName: string = '老师'
let isLoading: boolean = false
// 等等...
2
3
4
5
# 对象类型
数组类型的写法
// 写法一:
let numbers: number[] = [1, 3, 5]
// 写法二:
let strings: Array<string> = ['a', 'b', 'c']
2
3
4
对象类型的写法
let person:{} = {} //空对象
let person:{name:string} = {
name:'yaudh'
}
//有属性和方法的对象
let person:{name:string;sayHi():void}={
name:'jack',
sayHi(){}
}
//可以通过换行来分隔多个属性类型
let person:{
name:string
sayHi():void
}={
name:'jack',
sayHi(){}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 使用
{}
来描述对象结构 - 属性采用
属性名:类型
形式 - 方法采用
方法名():返回值类型
形式 - 描述的属性或方法之间使用
;
分隔
同样可以使用新增类型的方式
// 创建类型别名
type Person = {
name: string
sayHi(): void
}
// 使用类型别名作为对象的类型:
let person: Person = {
name: 'jack',
sayHi() {}
}
//带参数同样使用
type Person = {
greet(name: string): void
}
let person: Person = {
greet(name) {
console.log(name)
}
}
//箭头函数形式
type Person = {
greet: (name: string) => void
}
let person: Person = {
greet(name) {
console.log(name)
}
}
//可选对象属性
type Config = {
url: string
method?: string
}
function myAxios(config: Config) {
console.log(config)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
- 类型别名
- 带参类型
- 箭头函数形式
- 可选对象
# 新增类型
# 联合类型
需求:数组中既有 number
类型,又有 string
类型
语法:type|type
,由两个或多个类型组成的类型
let num:string | number = 18
num = 'abc'
let timer:number | null = null
timer = setInterval(()=>{},1000)
let arr:(number|string)[] = [1,'a']
2
3
4
5
# 类型别名
为任意类型起别名
使用场景:当同一类型被多次使用时,可以通过类型别名,简化该类型的使用
type CustomArray = (number | string)[]
let arr1: CustomArray = [1, 'a', 3, 'b']
let arr2: CustomArray = ['x', 'y', 6, 7]
2
3
4
- 使用
type
关键字类创建自定义类型 - 类型别名推荐使用大写字母开头,同类型注解的使用
# 函数类型
函数类型实际上指定的是:函数参数类型
和 返回值类型
方式一
function add(num1:number,num2:numer):number{
return num1+num2
}
const add = (num1:number,num2:numer):number{
return num1+num2
}
2
3
4
5
6
方式二
type AddFn = (num1: number, num2: number) => number
const add: AddFn = (num1, num2) => {
return num1 + num2
}
2
3
4
5
只适用于箭头函数的函数表达式类型声明
# void类型
如果函数没有返回值,可以指定函数类型为 void
function greet(name: string): void {
console.log('Hello', name)
}
// 如果什么都不写,此时,add 函数的返回值类型为: void
const add = () => {}
// 这种写法是明确指定函数返回值类型为 void,与上面不指定返回值类型相同
const add = (): void => {}
// 但,如果指定 返回值类型为 undefined,此时,函数体中必须显示的 return undefined 才可以
const add = (): undefined => {
// 此处,返回的 undefined 是 JS 中的一个值
return undefined
}
2
3
4
5
6
7
8
9
10
11
12
13
# 可选参数
使用函数实现某个功能时,参数可以传也可以不传,这种情况下,在给函数指定类型时,可以使用 可选参数
function mySlice(start?: number, end?: number): void {
console.log('起始索引:', start, '结束索引:', end)
}
2
3
注意: 可选参数只能在参数列表的前面,需要符合逻辑
同样的在 ts
中也能使用参数默认值:start:number=1
# 接口
当一个对象类型被多次使用时,一般会使用接口 interface
来描述对象的类型
interface Iperson{
name:string
age:number
sayHi():void
}
let person:Iperson={
name:'jack'
age:19
sayHi(){}
}
2
3
4
5
6
7
8
9
10
- 使用
interface
关键词,变量名称推荐使用I
开头 - 只能对
对象类型
指定,不同于type
的类型别名
继承特性
- 如果两个接口之间有相同的属性或方法,可以将公共的属性或方法抽离出来,通过继承来实现复用
interface Point2D { x: number; y: number }
// 继承 Point2D
interface Point3D extends Point2D {
z: number
}
2
3
4
5
# 元组
元组( Tuple
)可以确切的标记出有多少个元素,以及每个元素的类型
let position: [number, number] = [39.5427, 116.2317]
- 场景:在地图中,使用经纬度坐标来标记位置信息
- 可以使用数组来记录坐标,那么,该数组中只有两个元素,并且这两个元素都是数值类型 number[]
# 枚举
有 字面量类型+联合类型组合 的功能
// 创建枚举
enum Direction { Up, Down, Left, Right }
// 使用枚举类型
function changeDirection(direction: Direction) {
console.log(direction)
}
// 调用函数时,需要应该传入:枚举 Direction 成员的任意一个
// 类似于 JS 中的对象,直接通过 点(.)语法 访问枚举的成员
changeDirection(Direction.Up)
2
3
4
5
6
7
8
9
10
11
- 使用
enum
关键字定义枚举 - 约定枚举名称以大写字母开头
- 枚举中的多个值之间通过
,
(逗号)分隔 - 定义好枚举后,直接使用枚举名称作为类型注解
枚举的值为:数字枚举、字符串枚举
- 字符串枚举没有自增长行为,因此,字符串枚举的每个成员必须有初始值
实现原理
enum Direction {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}
// 会被编译为以下 JS 代码:
var Direction;
(function (Direction) {
Direction['Up'] = 'UP'
Direction['Down'] = 'DOWN'
Direction['Left'] = 'LEFT'
Direction['Right'] = 'RIGHT'
})(Direction || Direction = {})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# any类型
可以对该值进行任意操作,并且不会有代码提示
let obj: any = { x: 0 }
obj.bar = 100
obj()
const n: number = obj
2
3
4
5
任意类型,字面意思
# 类型推导
在 Ts
中,某些没有明确指出类型的地方,TS
的类型推断机制会帮助提供类型
- 变量声明并初始化
- 决定函数的返回值
// 变量 age 的类型被自动推断为:number
let age = 18
// 函数返回值的类型被自动推断为:number
function add(num1: number, num2: number) {
return num1 + num2
}
2
3
4
5
6
7
可以查看方法等类型
console.log()
document.createElement()
2
# 字面量类型
let str1 = 'Hello TS'
const str2 = 'Hello TS'
2
str1
的类型为 string
,str2
的类型为 Hello TS
相当于
let str1:'Hello Ts' = 'Hello TS'
使用场景
字面量类型配合联合类型一起使用,用来表示一组明确的可选值列表
// 使用自定义类型:
type Direction = 'up' | 'down' | 'left' | 'right'
function changeDirection(direction: Direction) {
console.log(direction)
}
// 调用函数时,会有类型提示:
changeDirection('up')
2
3
4
5
6
7
8
9
在 redux
中可以用来指定 reducer
的 type
类型
# 类型断言
有时候你会比 TS 更加明确一个值的类型,此时,可以使用类型断言来指定更具体的类型
const aLink = document.getElementById('link')
这个方法获取的类型 太宽泛(不具体)
,无法操作 href
等 a
标签特有的属性或方法
这种情况下可以使用类型断言
//写法一
const aLink = document.getElementById('link') as HTMLAnchorElement
//写法二
// 该语法,知道即可:在react的jsx中使用会报错
const aLink = <HTMLAnchorElement>document.getElementById('link')
2
3
4
5
# typeof
TS 提供了 typeof 操作符:可以在类型上下文中引用变量或属性的类型(类型查询)
使用场景:根据已有的变量的值,获取该类型
let p = { x: 1, y: 2 }
function formatPoint(point: { x: number; y: number }) {}
formatPoint(p)
function formatPoint(point: typeof p) {}
2
3
4
5