TypeScript学习:TS 基础学习笔记
2-1 TS具备的优势
- 编译时静态类型检测:函数或方法传参或变量赋值不匹配时,会出现编译错误提示,规避风险
- 自动提示更清晰明确
- 引入了泛型和一系列的TS特有特性
- 强大的
d.ts生命文件:类似书目录,清晰直观展示了依赖库文件的接口、type类型、类、函数、变量等声明 - 轻松编译成JS文件,即使TS文件有错误,绝大多数情况也能编译出JS文件
- 灵活性高:尽管TS是一门强类型检查语言,但也提供了
any类型和as any断言,这也使得TS具备一定灵活性(虽然不建议)
2-2 - 2-8 常用的24种TS类型
基本类型
- number
- string
- boolean
- null
- undefined
- symbol
根类型
- Object
- {}
对象类型
- array
- object
- function
枚举
- enum
其他特殊类型
- any
- unknown
- never
- void
- tuple 元组
- 可变元组
合成类型
- 联合类型
- 交叉类型
字面量数据类型
2-9 枚举
为什么使用枚举
常量带来的局限性。方法参数不能定义为具体类型,之能初级使用 number、string 基本类型替代,降低了代码的可读性和可维护性
枚举带来的好处
- 有默认值和可以自增值,节省编码时间
- 语义更清晰,可读性增强:枚举是一种值类型的数据类型,方法参数可以明确参数类型为枚举类型
2-10 枚举的定义、取值和分类
数字枚举
ts
enum Week {
Monday = 1,
Tuesday,
Wendsday,
Thrisday,
Friday,
Sarturday,
Sunday,
}
// 具备双重映射
console.log('monday', Week.Monday) // 1
console.log('monday', Week['Monday']) // 1
console.log('monday', Week[1]) // Monday
console.log('monday', Week[5]) // Friday字符串枚举
单独映射,由 key 到 value
ts
enum WeekEnd {
Monday = '星期一',
Tuesday = '星期二',
Wendsday = '星期三',
Thrisday = '星期四',
Friday = '星期五',
Sarturday = '星期六',
Sunday = '星期日',
}
console.log('WeekEnd', WeekEnd.Friday) // 星期五
console.log('WeekEnd', WeekEnd['星期三']) // undefined
console.log('WeekEnd', WeekEnd[1]) // undefined2-11 解析枚举底层
2-13 any, unknown 的两点区别和应用场景
相同点:any和unknown可以是任何类的父类,所以任何类型的变量都可以赋值给 any 类型或 unknown 类型的变量`
不同点:
- any 也可以是任何类的子类,但
unknown不行,所以any类型的变量都可以赋值给其他类型的变量 - 不能拿
unknown类型的变量来获取任何属性和方法,但any类型的变量可以获取任意名称的属性和任意名称的方法
2-14 interface
接口:令一种定义对伊类型的类型。具有继承的特点,所以使用频率高于type
接口的应用场景
- 一些第三方包或者框架底层源码中有大量的接口类型
- 提供方法的对象类型的参数时使用
- 为多个同类别的类提供统一的方法和属性声明
如何定义接口 interface Xxx {}
继承接口 interface A extends B {}
新的接口只是在原来接口继承之上增加了一些属性或方法,这时就用接口继承 interface A inplements B
2-15 可索引签名
ts
interface Product {
name: string
price: number
account: number
[x: string]: any // 下面用 Symbol 和 数字作为key 也是可以的
}
let p: Product = {
name: 'xx',
price: 100,
account: 20,
[Symbol('like')]: false,
100: 'hahah',
}2-16 索引类型访问 + 更多理解
ts
const symId = Symbol('001')
interface Product {
[symId]: number | string
name: string
price: number
account: number
buy(): void
}
type A = Product(typeof symId)例:获取接口里所有的属性名的类型
ts
type Pkeys = keyof Product // "name"|"price"||"account"|"buy"|"typeof symId"
// 当一个值以字面量形式充当类型时,它的值就是它本身
type AllKeys<T> = T extends any ? T : never
type Pkeys2 = Allkeys<keyof Product>2-17 说说对 void 的理解
2-18 null 和 undefined 相关细节
2-19 TS 函数和 TS 函数类型,rest 参数
2-23 interface 和 type 区别
type和接口类似,都用来定义类型,但type和interface区别如下:
- 定义类型和范围不同
- interface 只能定义对象类型或接口当名字的函数类型
- type 可以定义任何类型,包括基础类型、联合类型、交叉类型和元组
接口可以
extends一个或者多个接口或类,也可以继承type,但type类型没有继承功能。但一般接口继承类和type的应用场景很少见用
type交叉类型&可让类型中的成员合并成一个新的type类型,但接口不能交叉合并接口可合并声明
2-24 元组 Tuple
满足以下 3 点的数组就是元组
- 在定义时每个元素的类型都确定
- 元素值的数据类型必须是当前元素定义的类型
- 元素值的个数必须和定义时个数相同
2-25 TS 数组和数组元素怎样同时为只读
ts
const account = [10, 20, 30]
// acount = [10, 20, 30, 40] 数组不可修改
account[0] = 100 // 但数组中的元素可被改变
const account2 = ['a', 'b', 'c'] as const
// account[1] = 2 不可改变,会报错2-26 可变元组及运用场景
ts
let payment: [string, number, number] = ['$', '10', '20']
// 可变元组:具备元组固定值又具有数组灵活性特点
let customers: [string, number, number, ...any[]] = ['$', '10', '20', '30', '40']2-27 可变元组标签(tag)
ts
// 可变元组解构
let [name, age, address, ...rest]: [name_: string, age: number, address: string, ...rest_: any[]] =
['fri', 24, '成都', 'hello world']2-28 类、静态属性
定义:类就是拥有相同属性和方法的一系列对象的集合
展开理解:类是一个模具,是从该类包含的所有具体对象中抽象出来的一个概念,类定义了它所包含的全体对象的静态特征和动态特征
2-29 何时用到静态成员
静态成员:静态属性+静态方法
ts
class DateUtil {
static formatDate() {}
static getHours() {}
static getMinutes() {}
static getSeconds() {}
}
// DateUtil.formatDate() 这样来调用2-30 TS 单例设计模式的实现
单例:一个类只允许外部获取到它的唯一的实例对象
立即创建单例模式 - 缺点是运行后直接就创建单例了
ts
class DateUtil {
static dateUtil = new DateUtil()
private constructor() {}
formatDate() {}
getHours() {}
getMinutes() {}
getSeconds() {}
}
const dateUtil1 = DateUtil.dateUtil
const dateUtil2 = DateUtil.dateUtil
console.log(dateUtil1 === dateUtil2) // true
dateUtil1.formatDate()
const dateUtil = DateUtil.dateUtil
export default dateUtil用到时再创建,性能好,但写法更麻烦些
ts
class DateUtil {
static dateUtil: DateUtil
static getInstance() {
if (this.dateUtil) {
this.dateUtil = new DateUtil()
}
return this.dateUtil
}
private constructor() {}
formatDate() {}
getHours() {}
getMinutes() {}
getSeconds() {}
}
const dateUtil1 = DateUtil.getInstance()
const dateUtil2 = DateUtil.getInstance()
console.log(dateUtil1 === dateUtil2) // true
dateUtil1.formatDate()
const dateUtil = DateUtil.getInstance()
export default dateUtil