目录
类型注解
类型注解:约束变量的类型
示例代码:
let age:number = 18
-
说明:代码中的
:number
就是类型注解 -
解释:约定了类型,就只能给变量赋值该类型的值,否则,就会报错
错误演示:
错误代码:
错误原因:将string类型的值赋值给了number类型的变量,类型不一致
let age:number = '18'
注意:ts 在编写代码的时候报错多了,但是在浏览器中执行的时候报错少了
TypeScript 类型概述
可以将 TS 中的常用基础类型分为两大类:
-
JS 自有类型
-
简单类型(
number
string
boolean
undefined
null
) -
复杂数据类型(数组,对象,函数等)
-
-
TS 新增类型
-
联合类型
-
自定义类型
-
接口
-
元组
-
字面量类型
-
枚举
-
void
-
any
-
泛型
-
...
-
简单类型
-
自有类型 - 简单类型:
number/string/boolean/undefined/null
-
特点:简单,这些类型,完全按照 JS 中类型的名称来书写
let num: number = 123
let str: string = 'abc'
let flag: boolean = true
let undefinedValue: undefined = undefined
let nullValue: null = null
数组类型
数组类型的两种写法:
// 方式一
// 语法:let 变量名: 类型[] = 数组值
let arr1: number[] = [1, 2, 3]
let arr2: string[] = ['a', 'b', 'c']
// 方式二(泛型)
// 语法:let 变量名: Array<类型> = 数组值
let arr3: Array<number> = [1, 2, 3]
let arr4: Array<string> = ['a', 'b', 'c']
注意:推荐使用方式一的写法
联合类型
联合类型:将多个类型联合在一起,成为一个类型。
// 需求1:一个变量,既可以是数字,又可以是字符串
let temp: number | string = 123
temp = 'abc'
// 需求2:一个数组,里面既有数字,又有字符串
let arr1: (number | string)[] = [1, 2, 3, 'a']
let arr2: Array<number | string> = [1, 2, 3, 'a']
自定义类型(类型别名)
自定义类型:当一个结构复杂的类型被多次使用时,可以创建一个自定义类型,来简化类型的使用。
-
使用 type 关键字,自定义一个类型
-
语法:type 自定义类型名字 = 具体的类型
-
自定义类型的名字推荐使用大写字母开头
let arr1: (number | string | boolean)[] = [1, 'a', true]
let arr2: (number | string | boolean)[] = [2, 'b', false]
// 方式一
type ArrType = (number | string | boolean)[]
let arr1: ArrType = [1, 'a', true]
let arr2: ArrType = [2, 'b', false]
// 方式二
type ArrItemType = number | string | boolean
let arr1: ArrItemType[] = [1, 'a', true]
let arr2: ArrItemType[] = [2, 'b', false]
函数类型
基本使用
函数类型:其实就是指定函数的 参数 和 返回值 的类型。
方式一:分别给参数和返回值添加类型
// 声明式函数
function sum(n1: number, n2: number): number {
return n1 + n2
}
// 箭头函数写法
const sum = (n1: number, n2: number): number => {
return n1 + n2
}
方式二:给函数整体添加类型
// 定义一个函数整体的类型(类似于箭头函数的写法)
type FnType = (n1: number, n2: number) => number
// 只有箭头函数能使用该方式
const sum: FnType = (n1, n2) => {
return n1 + n2
}
void 类型
void 类型:函数没有返回值时,返回值的类型为 void
// 如果函数没有返回值,返回值的类型是 void。
const sum = (n1: number, n2: number): void => {
console.log(n1 + n2)
}
// 如果函数没有返回值,返回值的类型也可以不写
const sum = (n1: number, n2: number) => {
console.log(n1 + n2)
}
函数的可选参数
可选参数:当函数的参数可传可不传时,给函数的参数指定类型时,就需要使用可选参数。
比如:数组的 slice 方法,可以 slice()
也可以 slice(1)
还可以 slice(1, 3)
// 可选参数:在可传可不传的参数后面添加一个 ?
const mySlice = (start?: number, end?: number) => {
console.log(start, end);
}
mySlice()
注意:可选参数 和 参数默认值,互斥,不能同时使用
对象类型
对象类型:对象是由属性和方法构成的。 所以 TS 的对象的类型,就是描述对象中的属性和方法的类型。
对象中的属性类型
// 在一行代码中指定对象的多个属性类型时,使用分号进行分隔
let person: { name: string; age: number } = {
name: 'zs',
age: 18
}
// 通过换行来指定对象的多个类型,可以省略分号
let person: {
name: string
age: number
} = {
name: 'zs',
age: 18
}
// 可以将类型提取出来
type PersonType = {
name: string
age: number
}
let person: PersonType = {
name: 'zs',
age: 18
}
对象中的函数类型
// 方式一
// 语法:函数名(参数: 参数类型): 返回值类型
let person: {
name: string
age: number
sayHi(friend: string): void
} = {
name: 'zs',
age: 18,
sayHi(friend) {
console.log('你好', friend)
}
}
// 方式二
// 语法:函数名: (参数: 参数类型) => 返回值类型
let person: {
name: string
age: number
sayHi: (friend: string) => void
} = {
name: 'zs',
age: 18,
sayHi(friend) {
console.log('你好', friend)
}
}
对象的可选属性或方法
在对象的属性或方法名后面加一个 ? 问号
type StudengType = {
name: string
gender: string
age: number
score?: number
study?(): void
play(): void
}
let student = {
name: 'zs',
gender: '男',
age: 18,
// score: 100,
// study() {},
play() {}
}
interface接口类型
基本使用
interface:可以定义对象的类型。
interface Person {
name: string
age: number
sayHi(): void
}
let person: Person = {
name: 'zs',
age: 18,
sayHi() {}
}
注意:interface 不能写在一行,加不加分号都可以
interface vs type
-
相同点:都可以给对象定义类型
-
不同点:
-
interface:只能为对象定义类型
-
type:不仅可以为对象定义类型,它还可以定义其他的任意类型
-
type 不能重复定义,interface 可以重复定义,重复定义的内容会合并
-
-
推荐:能用 type 就用 type
// 使用 interface 定义对象类型
interface Person {
name: string
age: number
sayHi(): void
}
// 使用 type 定义对象类型
type Person = {
name: string
age: number
sayHi(): void
}
// person 对象
let person: Person = {
name: 'zs',
age: 18,
sayHi() {}
}
// interface 可以重复定义,重复定义的内容会合并
// 重复定义的使用场景:为项目中引入的第三方库添加新的类型时可以使用
interface Person {
name: string
age: number
}
interface Person {
sayHi(): void
}
// type 不能重复定义
type Person = {
name: string
age: number
}
type Person = {
sayHi(): void
}
interface 继承
interface 继承:如果两个 interface 之间有相同的属性或方法,可以将公共的属性或方法抽离出来,通过继承来实现复用。
-
比如:这两个接口都有 x、y 两个属性,重复写两次,可以,但很繁琐
interface Point2D {
x: number
y: number
}
let point2D: Point2D = {
x: 100,
y: 100
}
interface Point3D {
x: number
y: number
z: number
}
let point3D: Point3D = {
x: 100,
y: 100,
z: 100
}
更好的方式:
interface Point2D {
x: number
y: number
}
interface Point3D extends Point2D {
z: number
}
let point2d: Point2D = {
x: 100,
y: 200
}
let point3d: Point3D = {
x: 100,
y: 200,
z: 300
}
type 的交叉类型也可以实现继承的功能
type Point2D = {
x: number
y: number
}
type Point3D = Point2D & {
z: number
}
let point2d: Point2D = {
x: 100,
y: 200
}
let point3d: Point3D = {
x: 100,
y: 200,
z: 300
}
Tuple元组类型
元组类型:是特殊的数组类型,它确切地知道数组具体包含多少个元素,以及每个元素的类型
使用示例:在地图中,使用经纬度来标记坐标位置
-
使用数组类型
// 使用数组类型的缺点:不严谨,因为该类型的数组中可以出现任意多个数字
let position: number[] = [116.2317, 39.5427]
使用元祖类型
let position: [number, number] = [39.5427, 116.2317]
类型推断
类型推断:在 TS 中,某些没有明确指出类型的地方,TS 会自动推断出类型
换句话说:由于类型推断的存在,有些地方的类型注解可以省略不写
发生类型推断的 2 种常见场景:
-
声明变量并初始化时
-
函数的返回值
// 1. 发生类型推断的场景1:声明变量并初始化时
let age = 18
// 相当于
let age: number = 18
// 2. 发生类型推断的场景2:函数的返回值
const sum = (n1: number, n2: number) => {
return n1 + n2
}
// 相当于
const sum = (n1: number, n2: number): number => {
return n1 + n2
}
-
推荐:对于初学者,类型注解尽量写全,后期能省略类型注解的地方就省略(充分利用TS类型推论的能力,提升开发效率)
-
技巧:如果不知道类型,可以通过鼠标放在变量名称上,利用 VSCode 的提示来查看类型