一: TypeScript 简述
1: 什么是TypeScript ?
Typescript 不是一门全新的语言, 它相当于是 JavaScript 的超集, 对 js 进行了一些规范和补充,
2: 为什么要使用 TypeScript
js 只会在运行时去做数据类型检查, 而 ts 作为静态类型语言, 其数据类型是在编译期间确定的, 编写代码的时候, 要明确变量的数据类型, 使用 ts 后, 就不会出现因为数据类型错误导致的代码运行异常
3: 安装 TypeScript
$ npm install -g typescript
或者是淘宝镜像
$ cnpm i -g typescript
// 创建 index.js 文件 const msg:string = 'hello' console.log(msg) // 在当前文件所在的目录运行命令 $ tsc index.ts // 会生成一个同名的 index.js 文件, 然后在使用 node 命令运行 index.js 文件 $ node index.js // 运行成功即可以再 控制台打印 hello 内容
使用 ts-node 快速编译 Typescript
// 安装 ts-node $ npm install -g ts-node // 或者淘宝镜像 $ cnpm i -g ts-node // 使用 ts-node 可以快速运行 .ts 文件, 无需先转成 js 再运行, // 使用 ts-node 运行 index.ts 文件 $ ts-node index.ts // 如果 运行 ts-node 命令报错, 提示 Error: Cannot find module '@types/node/package.json' // 需要安装 相关依赖 $ npm install -g tslib @types/node
二: TypsScript 中的基本数据类型
1: 变量声明:
同 js 一样, 可以使用下面三个关键字: var let const
2: ts 中的 基本类型
- 注意:
- Typescript 中描述类型要用 小写 例如: boolean, number, string
- 大写开头的如: Boolean, Number, String 代表的是 js 的构造函数
- 原始类型: boolean, number string void null undefind bigint symbol
- 元组: tuple 表示已知元素数量和类型的数组, 各元素的类型不必相同, 对应未知的类型需要 相同
-
// 元组: 用来表示已知元素数量和类型的数组, 各个元素的类型不必相同, 对应未知的类型需要相同 let x:[string, number]; x = [ 'hello' , 1] // 运行正常 x = [1, 'hello'] // 报错
- 枚举: enum 枚举类型用于定义数值集合
-
// 枚举类型用于定义数值集合 // 数字枚举 会从0开始, 依次为元素赋值 enum Color { Blue, Red, Green } console.log(Color.Blue) // 输出 0 // 使用 数字枚举 let a:Color = Color.Blue console.log(a) // 输出 0 // 反向映射 console.log(Color[0]) // 输出字符串类型的 Blue // 可以为数字枚举手动赋值 enum Color { Blue = 10, Red, Green } console.log(Color.Blue) // 输出 10 console.log(Color.Red) // 输出 11 // 反向映射 console.log(Color[0]) // 输出 undefind // 字符串枚举 enum Color { Blue = 'BLUE', Red = 'RED', Green = 'GREEN' } console.log(Color.Blue) // 输出字符串类型 BLUE let str = 'RED' console.log(str === Color.Red) // 输出 true
- 任意: any 声明为 any 的变量可以赋值为任意类型的值,
- 未知: unknown
- never
- 数组 : Array 对象: object
void: 用于表示方法返回值的类型, 表示该方法没有返回值, 是一个返回值的占位符
当方法没有返回值时, 使用 void 作为 占位符
function fn () : void {
alert('hello world')
}
never:
其他类型(null 和 undefined)的子类型, 代表从不会出现的值, 意味着声明为 never类型的变量只能被 never类型所赋值, 在函数中通常表现为抛出异常或无法执行到终止点(例如无线循环)
BigInt类型
js 中可以用 Number 表示最大的整数为 2^53 - 1 , 如果超过了这个界限, 可以用BigInt来表示, 它可以表示任意大的整数
- 在一个整数字面量后加 n 的方式定义 一个 BigInt, 如: 10n 或者调用函数 BigInt()
const bigInit: bigint = 123456789n
const alsoHuge: bigint = BigInt(123456789)
const hugeString: bigint = BigInt('123456789')
bigInit === alsoHuge // true
bigInit === hugeString // true
- BigInt 与 Number 的不同点
- BigInt 不能用于Math对象的方法
- BigInt 不能和 Number 实例混合运算, 两者必须转换成同一种类型
- BigInt 变量在转换为 Number 变量时可能会丢失精度
Symbol 类型
-
symbol 是一种基本数据类型
-
symbol()函数 会返回 symbol 类型的值, 每个从Symbol()返回的symbol 值都是唯一 的
-
const sym1: symbol = Symbol() const sym2: symbol = Symbol('foo') const sym3: symbol = Symbol('foo')
-
上面的代码创建了 3 个新的 symbol 类型, 但是每一个从 Symbol()返回的值都是唯一的
元组: (Tuple)
- 相同类型元素组成为数组, 不同类型元素组成了元组
- 元组中规定的元素类型顺序必须是完全对照的, 而且不能多, 不能少,
unKnown 类型
- any 无需事先执行任何类型的检查, 可以是任何类型
- unknown 类型, 在被确定为某个类型之前, 不能被进行诸如函数执行, 实例化等操作, 一定程度上对类型进行了保护
三: 接口
概念: 1: 接口是对 js 本身的随意性进行约束, 通过定义一个接口, 约定了变量, 类, 函数等应该按照什么样的格式进行声明, 实现多人合作的一致性
2: 接口中只能定义抽象方法和抽象方法,
3: 接口中没有构造方法, 不能被实例化, 只能被类实现
4: 当类实现接口时, 要重写该接口的所有抽象方法和其父接口上的所有抽象方法
应用场景: 在声明一个对象 函数 或者类时, 先定义接口, 确保其数据结构的一致性, 在多人协作时, 定义接口尤为重要
接口中的属性:
// 定义一个接口
interface Person {
name: string;
age: number;
height: number;
}
// 接口的可选属性
interface Person {
name?: string; // 可选属性
readonly age: number; // 只读属性
height: number;
}
// 接口的任意属性
interface Preson {
name: string;
age: number;
[nicheng: string]: any; // 只要不是 name, age 他们可以是任意的类型
}
// 类 类型
interface Animal {
name: string
}
class Dog implements Animal {
name: string;
constructor(name: string){
this.name = name
}
}
// 可选属性, 与普通接口差不多, 只是这个属性可以不使用
// 只读属性. 这个属性只有在刚刚创建的时候修改其值, 之后不能被修改
// 函数类型: 为了使接口表示函数类型, 我们需要给接口定义一个调用签名, 就像是一个只有
// 参数列表, 和 返回值类型 的的函数定义
// 可以使用 implements 让类遵循接口定义
// 接口继承
interface A {
say()
}
interface B {
run()
}
interface C extends A, B {
// 接口 C 可以继承 接口A 和B 的属性
}
// 一个接口可以实现多个继承
四: 类
概念: 1: 用 class声明类型, 表示具有相同属性和方法的一类对象的群体
2: 通过 class 关键字声明一个类, 主要包含以下模块: 属性, 构造函数, 方法
3: constructor() 方法是类的默认方法, 通过 new 关键字生成实例对象时, 会自动调用该 方法, constructor()方法默认会返回实例对象
4: super() 表示父类对象
类的继承: 类的继承是单继承, 使用 extends 继承, 子类可以继承父类所有非私有的属性和方法
成员(实例属性, 实例方法)的访问权限:
1: public, 公共的, 全局都可以访问
2: protected 受保护的, 只有当前类及其子类可以访问
3: private 私有的只有当前类可以访问
4: readonly: 只读属性必须在声明时或构造函数里被初始化
类的封装: 1: 对所有的成员属性私有化
2: 对外提供公开的get 和 set 方法
抽象类: 1: abstract 关键字是用于定义抽象类和抽象类内部定义抽象方法
2:抽象类作为其他派生类的基类使用, 他们一般不会直接被实例化, 不同于接口, 抽 象类可以包含成员的实现细节
3: 当一个类中声明了抽象方法, 那么该类必须是抽象类
4: 抽象类不能被实例化
方法重写: 1: 当子类继承父类方法, 父类方法不能满足子类需求时, 子类可以重写该方法
2: 当子类重写了父类方法后, 子类对象调用的是重写后的方法
3: 当使用多态时, 父类引用调用子类重写的方法, 执行的是重写后的那个方法
4: 当子类重写父类方法时, 该方法的访问权限不能小于父类中该方法的访问权限
多态的实现: 1: 实现继承
2: 子类重写父类方法
3: 父类引用执行子类对象
泛型:
概念: 1: 通俗来讲是指在定义函数, 接口或者类时, 未指定其参数类型, 只有在运行时传入才能 确 定 ,
2: 泛型的使用可以帮助我们为不同类型的输入, 复用相同的代码
泛型的约束:
通过 extends 关键字来实现泛型约束: 1: T extends IProps
2: T extends IProps & IBase
联合类型: let i: string | number
交叉类型: let i:Props & IBase
映射类型: Readonly 与 Partial 关键字