一. 类型注解的作用
let name:string = '字符串'
//1. 将来不能把其他类型的值赋值这个变量, 减少开发隐藏问题;
name = 100 // error
//2. 写代码有提示, 比如在VScode中, 在变量后边敲一个 . 可以直接看到当前类型所支持的方法或属性;
name.substr()
二. 有哪些数据类型?
-
JS已有类型:
- 简单类型: number / string / boolean / null / undefined
- 复杂类型: 数组 / 函数 / 对象(看代码!)
// 例: 声明一个只能包含字符串类型的数组 //数组类型注解1 let arr: string[] = ['a', 'b'] //数组类型注解2 let arr: Array<string> = ['a', 'b']// 函数声明: ts要求必须给函数参数定义类型, 而返回值会自动推断(可以不写) function addNum(a: number, b: number): number { return a + b } let fn = (a:number, b:number): number => { return a + b } // 函数的类型别名, ,有点像箭头函数 但不是 (通常是给箭头函数或者函数表达式使用, 不会给函数声明'function'使用) type FnType = (a:number, b:number) => number let add: FnType = (a, b) = { return a + b } // 可选参数, 使用参数? , 表示参数可传可不传, (注意 可选参数不能在必选参数前面), 也可用于对象属性, 表示可选属性(可有可无) let print = (name: string, gender?: string): void => { console.log() }// 对象类型 // 最大的好处就是描述了对象结构, 以后用到此对象的时候, 编辑器可以直接提示对象里的属性和方法, 避免出错 // 常见使用场景: 定义好后端api返回的数据结构, 每次使用就不用去看接口返回字段了 let obj:{ name: string, gender: string, sayHi: (content: string) => void } = { name: '小丽', gender: '未知', sayHi(content) { console.log('无语'+content) } } // 使用类型别名 type Person = { name: string, gender: string, sayHi: (content: string) => void } let obj1:Person = { name: '小帅', gender: '男', sayHi(content) { console.log('无语'+content) } } //可选属性的一些问题 let obj:{ name: stringg, girlFriend: string, gender?: string } = { name: '小智', girlFriend: '小韩', gender: '男' } obj.gender.concat() //会报错, 因为gender是可选属性, 可能会不存在 //可选链操作符, 解决可选属性 不确定的问题 obj.gender?.concat() -
TS新增类型:
- 联合类型 (可以把类型使用 | 链接起来, 代表'或') (看代码!)
//使用联合类型时, 代码提示只提示两种类型共有的方法 let timer: number | null = null timer = setTimeout(() => {}, 2000) let arr:(number | string) = [1, 2, 'a']- 自定义类型 (类型别名, 使用关键字 type )
//相当于把稍复杂的类型封装起来 type ArrType = (number | string)[] let arr1:ArrType = ['a', 1, 2] let arr2:ArrType = [1, 2, 'c'] type Person = { name: string, gender: string, age?: number, say: (msg:string) => viod } let obj:Person = { name: '小韩', gender: '女', age: 18, say: (msg) => { console.log(msg) } } //还可以组合使用 type ItemType = number | string let str: ItemType[] = [1, 2, 3]- 接口 (用于限制对象的属性和方法, 使用interface)
//interface 与 type 的区别: // 1. interface只能给对象指定类型, 而type可以给任意类型指定别名 // 2. interface每一个属性后不用写逗号 interface IPerson { name: string say: (name:string) => viod } let obj:IPerson = { name: '小丽', say: (name) => { console.log('哈哈哈'+name) } }- void (用于不需要返回值的函数, 表示空)
// 如果不写return, ts自动推断类型为viod, 因为如果用undefined, 表示函数必须只能返回undefined function Fn(a, b): void { console.log(a, b) }- 字面量 (值必须为字面量值)
// 常常搭配联合类型一起使用, 表示值只能为up 或 down 其中一个 type Direction = 'up' | 'down' function changeDirection(direction: Direction) { console.log(direction) } changeDirection('up')- 元祖 (固定长度和类型的数组)
// 使用场景: 记录坐标, 数组只有两个元素, 且都是数值型 let arr: [number, number] = [39.1245, 116.4255]- 枚举enum 定义一组命名常量, 描述一个值, 值只能是这些命名常量中的一个
// 使用场景: 用户选择上/下/左/右, 但是后端要的值为 0(上) 1(下) 2(左) 3(右) enum Direction { Up, //0 不指定值 默认为0 1 2 3.. 递增 Down, //1 Left, //2 Right //3 } function changeDirection(direction: Direction) { console.log(direction) } changeDirection(Direction.Up) //打印 0 //也可以指定值 enum Direction { Up = '上', Down = '下', Left = '左', Right = '右' } changeDirection(Direction.left) //打印 左 // 个人理解类似于字典, 建立对应关系, 可以通过键找值, 也可以通过值找键 // 内部实现 实际上就是js对象- any类型 表示可以是任何类型, 可以对其进行任意操作 (不建议使用, 会失去使用ts类型保护的优势, 变成anyscript)
三. insterface(接口)的继承
使用extends关键字, 实现接口的继承, 继承后者所有约束
interface IPerson {
name: string
age: number
sayHi: () => void
}
//Istudent 具备 IPerson 的所有约束规则
interface Istudent extends IPerson {
score: number
sleep: () => void
}
let obj:interface = {
name: '小智',
age: 18,
score: 130,
sayHi: () => {
alert('Hi')
},
sleep: () => {
alert('我睡了')
}
}
四. type怎么实现类似继承的效果?
type Person = {
name: string,
gender: string
}
// 使用 & 连接符, 表示既要满足前面的 也要满足后面的, 变相的实现继承
type Student = {
score: number
} & Person
let obj: Student = {
name: '小丽',
gender: '男',
score: 150
}