文章目录
- 1. 类型注解
- 2. 原始类型
- 3. 数组类型
- 4. 联合类型
- 5. 类型别名
- 6. 函数类型
- 7. 对象类型
- 8. 接口类型
- 8.1 接口声明
- 8.2 接口继承
- 9. 元组类型
- 10. 类型断言
- 11. 字面量类型
- 12. 枚举类型
- 12.1 数字枚举
- 12.2 字符串枚举
- 13. any 类型
- 14. typeof 运算符
1. 类型注解
前言:
① TS 是 JS 的超集,它提供了 JS 的所有功能,并且额外的增加了类型系统;
② 所有的 JS 代码都是 TS 代码;
③ JS也有类型(比如,number、string 等),但是 JS 不会检查变量的类型是否发生改变,而 TS 会检查;
④ TS 类型系统的主要优势:可以显示标记处代码中的意外行为,从而降低了发生错误的可能性。
//: number 就是类型注解
let age: number = 2
2. 原始类型
let age: number = 2
let name: string = '栈老师'
let isLoading: boolean = false
let a: null = null
let b: undefined = undefined
let s: symbol = Symbol()
3. 数组类型
//数组类型的两种写法(推荐使用第一种)
let numbers: number[] = [1, 3, 5]
let strings: Array<string> = ['a', 'b', 'c']
4. 联合类型
需求:数组中既有 number 类型,又有 string 类型。
//数组中既有 number 类型,又有 string 类型。
let arr: (number | string)[] = [1, 2, '栈老师']
//不添加小括号表示,既可以是number类型,又可以是string[]类型
let arr: number | string[] = ['栈老师']
5. 类型别名
场景:当同一类型被多次使用时,可以通过类型别名,来简化该类型的使用。
//通过type关键字声明类型别名
type CustomArray = (number | string)[]
let arr1: CustomArray = [1, 2, '栈老师']
创建自定义的类型别名后,直接使用该类型别名作为变量的类型注解即可!
6. 函数类型
//返回值为number类型
function add(num1: number, num2: number): number {
return num1 + num2
}
//没有返回值用void
function greet(name: string): void {
console.log(name)
}
//参数可传可不传,加问号
function myTest(name: string, age?: number): void {
console.log(name, age)
}
函数声明方式声明函数:
函数表达式方式声明函数:
可选参数,在可传可不传的参数后面加 ?(问号),注意可选参数只能放在参数列表的最后,必选参数应该放在最前面。
7. 对象类型
let person: {name: string; age: number; sayHi(): void} = {
name: '栈老师',
age: 24,
sayHi() {}
}
用花括号描述对象结构,在一行代码中指定多个属性类型时,使用分号来隔开,对象可选属性的语法与函数可选参数的语法一致,直接在可选属性的后面加问号即可!
8. 接口类型
8.1 接口声明
当一个对象类型被多次使用时,一般会使用接口来描述对象的类型,达到复用的目的。
//使用interface指定别名
interface IPerson {
name: string;
age: number;
sayHi(): void
}
//使用type指定别名
type IPerson = {
name: string;
age: number;
sayHi(): void
}
let person: IPerson = {
name: '栈老师',
age: 24,
sayHi() {}
}
注意点:
① 使用 interface 关键字来声明接口;
② 直接使用接口名称作为变量的类型;
③ 也可以使用 type 来指定别名,只不过 interface 只能为对象类型指定别名,并且可以继承,而 type 可以为任意类型指定别名,但不能继承。
8.2 接口继承
如果两个接口之间有相同的属性或方法,可以将公共的属性或方法抽离出来,通过继承来实现复用。
//继承后,Point3D就有了Point2D的属性和方法
interface Point2D {x: number; y: number}
interface Point3D extends Point2D {z: number}
9. 元组类型
let position: [number, number] = [25, 71]
元组类型可以确切地标记出有多少个元素,以及每个元素的类型!
10. 类型断言
const aLink = document.getElementById('link') as HTMLAnchorElement
① 使用 as 关键字实现类型断言;
② 关键字 as 后面的类型是一个更加具体的类型;
③ 通过类型断言,aLink 的类型变得更加具体,这样就可以访问 a 标签特有的属性或方法了。
11. 字面量类型
let str1 = 'hello'
const str2 = 'hello'
通过 TS 类型推论机制,可以得到答案:str1 的类型为 string,str2 的类型为 hello。
注意点:
① str1 是一个变量(let),它的值可以是任意字符串,所以类型为 string;
② str2 是一个常量(const),它的值不能变化只能是 hello,所以它的类型为 hello。
此处的 hello 就是一个字面量类型,也就是说某个特定的字符串也可以作为 TS 中的类型!
使用场景:字面量类型可以配合联合类型一起使用,用来表示一组明确的可选值列表。
//direction的类型只能是up或down
function changeDirection(direction: 'up' | 'down') {
console.log(direction)
}
相比于 string 类型,使用字面量类型更加精确、严谨!
12. 枚举类型
枚举:定义一组命名常量,类似字面量类型加联合类型的组合,它描述一个值,该值可以是这些命名常量中的一个。
enum Direction {Up, Down}
function changeDirection(direction: Direction) {
console.log(direction)
}
changeDirection(Direction.Up)
注意点:
① 约定枚举名称、枚举中的值都以大写字母开头;
② 枚举中的多个值之间通过逗号分隔;
③ 定义好枚举后,直接使用枚举名称作为类型注解;
④ 类似 JS 中的对象,通过 Direction.Up 来访问枚举中的成员。
12.1 数字枚举
枚举成员也是有值的,默认从 0 开始自增,Direction.Up 的值为 0。当然也可以给枚举中的成员初始化值:
enum Direction {Up = 10, Down = 2}
12.2 字符串枚举
字符串枚举没有自增长行为,因此,字符串枚举的每个成员必须有初始值。
enum Direction {Up = ‘UP’, Down = 'Down'}
其他类型仅仅被当做类型,而枚举不仅用作类型,还提供值,也就是说,其他的类型在编译为 JS 代码时会自动移除,但枚举类型会被编译为 JS 代码!
一般情况下,推荐使用字面量类型 + 联合类型组合的方式,因为相比枚举,这种方式更加直观、简洁和高效!
13. any 类型
当值的类型为 any 时,可以对该值进行任意操作,并且不会有代码提示。
let obj: any = {x: 0}
即使存在错误也不会给出提示,所以不推荐使用 any 类型!
14. typeof 运算符
typeof 不仅可以获取数据类型,还可以在类型上下文中引用变量或属性的类型,以此来简化书写。
let p = {x: 1, y: 2}
function formatPoint(point: typeof p) {}
formatPoint(p)