1. 安装TS
npm i -g typescript
查看是否TS安装成功
tsc
显示图片中内容表示安装成功
2. 编译TS代码
Node.js/浏览器,只认识 JS 代码,不认识 TS 代码。需要先将 TS 代码转化为 JS 代码,然后才能运行
tsc xxx.ts
ts编译js的过程
3. 简化编译TS代码
- 问题描述:每次修改代码后,都要重复执行两个命令,才能运行 TS 代码,太繁琐。
- 简化方式:使用 ts-node 包,直接在 Node.js 中执行 TS 代码。
- 安装命令:npm i -g ts-node(ts-node 包提供了 ts-node 命令)。
- 使用方式:ts-node hello.ts。
- 解释:ts-node 命令在内部偷偷的将 TS -> JS,然后,再运行 JS 代码。
ts-node hellos.ts
4. TS的类型
类型 | 描述 | 例子 |
---|---|---|
number | 任意数字 | 1,-1,1.11 |
string | 任意字符串 | “hi”,'hi',hi |
boolean | 布尔值 | true,false |
字面量 | 限制变量的值就是该字面量的值 | 其本身 |
any | 任意类型 | * |
unknown | 类型安全的any | * |
void | 没有值或undefined | 空值或undefined |
never | 不能是任何值 | 没有值 |
object | 任意js对象 | { name: '张三' } |
array | 任意js数组 | [1,2,3] |
tuple | 元素,TS新增类型,固定长度数组 | [4,5] |
enum | 枚举,TS新增类型 | enum(A,B) |
4.1 字面量类型声明(场景少)
下面这种方式声明的不能修改值
let a: 10
a = 10 // 打印 10
a = 20 // 报
a = '20' // 报错
使用 | 连接多个类型(联合类型)
let b: 'abc' | '123'
b = 'abc' // 打印 abc
b = '123' // 打印 123
let c: boolean | string
c = 'abc' // 打印 abc
c = true // 打印 true
4.2 number类型
let a:number = 10
a = 10 // 打印 10
a = 20 // 打印 20
a = '20' // 报错
4.3 string类型
let a:string = '10'
a = '100' // 打印 100
a = 'hello' // 打印 hello
a = 20 // 报错
a = false // 报错
4.4 boolean类型
let a:boolean = true
a = false // 打印 false
a = true // 打印 true
a = 'true' // 报错
let b:boolean = Boolean(1) // 也可以使用Boolean转译
b // 打印 true
4.5 any类型(尽量少用)
- 设置了any,相当于对该变量关闭了TS的类型检测
- any类型变量,它就可以赋值给任意变量
- 不设置类型时,默认是any类型
let a:any
let b // 不设置类型时,默认是any类型
a = 10 // 打印 10
a = true // 打印 true
a = '20' // 打印 20
let b:string
b = a // 不报错,a是any类型,它就可以赋值给任意变量
4.6 unknown类型
- unknown表示未知类型, 是一个安全的any
- unknown类型的变量,不能直接赋值给其它变量
let a:unknown
a = 10 // 打印 10
a = true // 打印 true
a = '20' // 打印 20
let b:string
a = 'hi'
b = a // 报错,a的值虽然是字符串,但类型是unknown,所以不能赋值给为string的b
// 如果要把unknown类型的值赋值给其它变量,则可以使用类型断言,有两种方法:
b = a as string // 可以告诉解析器变量的实际类型
b = <string>a
4.7 void类型(多用于函数)
- void用来表示空,以函数为例,就表示没有返回值的函数
- void类型的用法,主要是用在我们不希望调用者关心函数返回值的情况下,比如通常的异步回调函数
- void是函数没有显式返回任何值(例如consloe.log)时的返回类型
function voidFn(): void {
console.log('test void')
}
voidFn()
4.8 never类型
- never是函数根本不返回(例如函数抛出异常,或者永远运行下去)时使用的类型
function neverFn(): never {
throw new Error('test never')
}
neverFn()
4.9 object类型(几乎不用)
- object 代表所有非值类型的类型,例如数组、对象、函数等,常用于泛型约束
- 在js中万物皆对象,所以object几乎很少用
let a:object
a = {}
a = function () {}
- 在使用{}指定对象中可以包含哪些属性
- 语法:{属性名:属性类型,属性名:属性类型,属性名?:属性类型}
- {属性名:属性类型}表示必填参数,不写报错
- {属性名?:属性类型}表示可选参数
- [propName:string]:any 表示任意类型的属性
let b:{name:string,age?:number,[propName:string]:any}
b = { name: '张三', age: 20, a: 123, b: 'hi'}
4.10 array类型
语法
- let xx:类型[]
- let xx:Array<类型>
let a:string[]
或
let a:Array<string>
a = ['a', 'b', 'c']
let b:number[]
或
let b:Array<number>
b = [1, 2, 3]
4.11 tuple类型
- tuple是元组类型,表示固定长度的数组
- 语法:[类型,类型,类型]
let a:[string,number]
a = ['a', 2] // 打印 ['a',2]
a = ['a', 2, 3] // 报错,不能超过元组定义时的元素个数
4.12 enum类型
- enum表示枚举类型
// 定义性别的枚举对象
enum Gender{
Male = 0,
Female = 1
}
let a: { name:string,gender:Gender }
a = {
name: '张三',
gender:Gender.Male
}
console.log(a.gender===Gener.Male) // 打印 true
5. 类型的别名
- 用于简化类型的定义
let a: 1 | 2 | 3 | 4 // 表示a可以定义的值是1234其中一个
let b: 1 | 2 | 3 | 4
a = 1 // 打印 1
a = 5 // 报错
// 可以简化为
type myNum = 1 | 2 | 3 | 4
let a: myNum
let b: myNum
6. 类(class)
含义:它是用来创建具有相似属性和行为的对象的一个模板或蓝图。类定义了对象的属性(成员变量)和行为(成员函数),并通过创建对象来实例化类。对象是具有类类型的变量
类与对象的关系:
(1)类是对象的抽象,而对象是类的具体实例
(2)类是抽象的,不占用内存,而对象是具体的,占用存储空间
(3)类是用于创建对象的规划,抽象
6.1 创建类
// 语法
class 类名{
属性:类型
...
constructor(参数1:参数1类型,参数2:参数2类型,...){
this.属性 = 参数1
...
}
方法(){
方法体
}
...
}
例子
class Dog {
name : string
age : number
# 构造函数,会在对象创建时调用
constructor(name : string, age : number) {
this.name = name
this.age = age
}
say() {
console.log('汪汪汪汪');
}
}
const dog = new Dog('旺财', 3)
console.log(dog);
dog.say()
类的基本用法
6.2 类的继承
基础用法
// 父类
class Animal{
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
say() {
console.log(this.name + '在汪汪叫')
}
}
// 子类
# 子类使用extends关键字来表示继承父类
class Dog extends Animal{
# 子类中也可以有自己的属性和方法
sex: string
# super表示当前类的父类
# 构造函数中必在最前面加上super来调用一下父类的属性
constructor(name: string, age: number, sex: string) {
super(name, age)
this.sex = sex
}
run() {
console.log(`一只叫${this.name}${this.age}岁的${this.sex}狗在跑`)
}
# 如果子类中也定义了与父类中一样的方法,会覆盖父类中的方法,见图2
say() {
console.log('子类重写父类的方法')
}
}
const dog = new Dog('旺财', 4)
console.log(dog);
dog.say()
dog.run()
图1
图2
6.3 抽象类
- 以abstract开头的类就是抽象类
- 抽象类和其它类区别不大,只是不能用来创建对象
- 抽象类就是专门用来被继承的类
- 抽象类中可以添加抽象方法
// 父类
abstract class Animal {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
/**
* 定义抽象方法
* 1.使用abstract开头,没有方法体
* 2.抽象方法只能定义在抽象类,子类必须对抽象方法进行重写
*/
abstract say(): void
}
// 子类
class Dog extends Animal {
sex: string
constructor(name: string, age: number, sex: string) {
super(name, age)
this.sex = sex
}
run() {
console.log(`一只叫${this.name}${this.age}岁的${this.sex}狗在跑`)
}
}
// const animal1 = new Animal() // 不能创建对象,会报错
const dog = new Dog('大黄',3,'公')
dog.run()
console.log(dog);
6.4 接口
- 接口用来定义一个类结构
// 描述一个对象的类型
type myType = {
name: string
age: number
}
// 不可重复声明
// type myType={
// sex:string
// }
/**
* 接口用来定义一个类结构
* 1.用来定义一个类中应该包含的属性和方法
* 2.接口也可以当成类型声明使用
* 3.可以重复声明,表示追加类的属性和方法
*/
interface myInter {
name: string
}
interface myInter {
age: number
}
// 用来规定类型声明,相当于type别名的用法
const obj: myInter = {
name: 'zs',
age: 20
}
/**
* 接口用来定义一个类结构
* 1.接口可以在定义类的时候用来限制类的结构
* 2.接口中的所有属性都不能有实际的值
* 3.接口只定义对象的结构,面不鼒实际值
* 4.有接口中所有的方法都是抽象方法
*/
interface animalInter {
name: string
say(): void
}
/**
* 定义类时,可以使类去实现一个接口
* 实现接口就是使类满足接口的需求
*/
class Animal implements animalInter {
name: string;
constructor(name: string) {
this.name = name
}
say(): void {
console.log('叫叫叫')
}
}
const dog = new Animal('小黑')
console.log(dog);
dog.say();
image.png
6.5 属性的修饰符
修饰符的作用是为了数据更加安全
修饰符 | 自身内部 | 子类内部 | 实例对象 |
---|---|---|---|
static | 可以访问 | 可以访问 | 不能访问 |
public | 可以访问 | 可以访问 | 可以访问 |
private | 可以访问 | 不能访问 | 不能访问 |
protected | 可以访问 | 可以访问 | 不能访问 |
- static:静态属性,修饰的属性只能通过类访问,实例对象不能访问
- public:公有属性,修饰的属性可以在任意位置访问和修改,属性默认就是public
- private:私有属性,只能在类内部进行访问和修改
- protected:受保护的属性,只能在当着类和当前子类中使用
// 属性的修饰符
class A {
_name : string
private _age : number
protected _sex : string
static _height : number = 180
constructor(name : string, age : number, sex : string) {
this._name = name
this._age = age
this._sex = sex
}
get age() {
return this._age
}
set age(value : number) {
if (value >= 0) {
this._age = value
}
}
}
const a = new A('ZS', 18, '男')
console.log(a);
console.log(a._name); // ZS
// console.log(a._age); // 不能访问
// 使用了get age,就可以使用a.age,直接访问
console.log(a.age); // 18
// 使用了set age,就可以使用a.age=xxx 正常赋值
a.age = 50
// console.log(a._sex) // 不能访问
console.log(a.age) // 50
// console.log(a._height) // 不能访问
console.log(A._height) // 180
image.png
6.6 类的属性的简写
class A{
constructor(public name:string,public age:number) {
}
}
const a = new A('zs',30)
console.log(a)
image.png