一、基本类型
1、类型声明
- 类型声明是TS非常重要的一个特点
- 通过类型声明可以指定TS中变量(参数、形参)的类型
- 指定类型后,当为变量赋值时,TS编译器会自动检查值是否符合类型声明,符合则赋值,否则报错
- 简而言之,类型声明给变量设置了类型,使得变量只能存储某种类型的值
2、自动类型判断
- TS拥有自动的类型判断机制
- 当对变量的声明和赋值是同时进行的,TS编译器会自动判断变量的类型
- 如果你的变量的声明和赋值同时进行,可以省略掉类型声明
3、类型
number
:任意数字string
:任意字符串boolean
:布尔值true或false字面量
:限制变量的值就是该字面量的值any
:任意类型,可以赋值给任意变量unkonwn
:类型安全的any,不能直接赋值给其他变量void
:没有值(或undefined),表示空,以函数为例,就表示没有返回值的函数never
:不能是任何值,表示永远不会返回结果object
:任意的js对象array
:任意的js数组tuple
:元祖,TS新增类型,固定长度的数组enum
:枚举,TS新增类型
4、编译选项
- 自动编译文件
①编译文件时,使用-w指令后,TS编译器会自动监视文件的变化,并在文件发生变化时对文件进行重新编译
tsc xxx.ts -w
- 自动编译整个项目
①如果直接使用tsc指令,则可以自动将当前项目下的所有ts文件编译为js文件
②但是能直接使用tsc命令的前提时,要现在项目根目录下创建一个ts的配置文件tsconfig.json
③tsconfig.json
,添加配置文件后,只需要tsc命令即可完成对整个项目的编译
④配置选项
include:指定哪些ts文件需要被编译
** 表示任意目录 * 表示任意文件
exclude:定义需要排除在外的目录 [“xx/xx”, “xx/xx”]
extends:定义被继承的配置文件
files:指定被编译文件的列表,只有需要编译的文件少时才会用到
compilerOptions:编译选项是配置文件中非常重要也比较复杂的配置选项,在compilerOptions 中包含多个子选项,用来完成对编译的配置
1、target 用来知道ts被编译为js的版本(es3、es5、es6、es2015、es2018、es2019、es2020…)
2、module:指定要使用的模块化标准(none、commonjs、amd、system、umd、es6、es2015、es2020…)
3、lib:指定项目中要使用的库
4、outDir:用来指定编译后文件所在的目录
5、outFile:将代码合并为一个文件,设置outFile后所有的全局作用域中的代码会合并到同一个文件中
6、allowJs:是否对js文件进行编译,默认是false
7、checkJs:是否检查js代码是否符合语法规范,默认是false
8、removeComments: true 是否移除注释
9、noEmit:false 不生成编译后的文件
10、noEmitOnError:true 当有错误时不生成编译后的文件
11、alwaysStrict:false 用来设置编译后的文件是否使用严格模式,默认是false
12、noImplicitAny:true 不允许隐式的any类型
13、noImplicitThis:true 不允许不明确类型的this
14、strictNullChecks:true 严格的检查空值
二、面相对象
1、类(class)
- 直接定义的属性是实例属性,需要通过对象的实例去访问
const per = new Person();
per.name
- 使用static开头的属性是静态属性(类属性),可以直接通过类去访问
Person.name
2、构造函数(constructor)
- 构造函数会在对象创建时调用
- 在实例方法中,this就表示当前的实例
- 在构造函数中当前对象就是当前新建的那个对象,可以通过this向新建的对象中添加属性
- 在方法中可以通过this来表示当前调用方法的对象
3、继承(extends)
- 使用继承后,子类会拥有父类所有的方法和属性
- 通过继承可以将多个类中共有的代码写在一个父类中,这样就只需要写一个即可让所有的子类同时拥有父类中的属性;如果希望在子类中添加一些父类中没有的属性或方法直接加就行
- 如果在子类中添加了和父类相同的方法,则子类方法会覆盖掉父类的方法,这种子类覆盖掉父类方法的形式叫做方法的重写
4、超类(super)
- 代表的是当前类的父类,最关键的是在子类的构造函数中必须调用父类的构造函数
5、抽象类(abstract)
- 以abstract开头的类是抽象类;抽象类和其他类区别不大,只是不能用来创建对象;抽象类就是专门用来被继承的类
- 抽象类中可以添加抽象方法,抽象方法使用abstract开头,没有方法体
- 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
6、接口(interface)
- 用来定义一个类的结构,用来定义一个类中应该包含哪些属性和方法,同时也可以当成类型声明去使用
- 可以在定义类的时候限制类的结构;接口中的所有属性都不能有实际的值,接口只定义对象的结构而不考虑实际值,在接口中所以的方法都是抽象方法
- 定义类时,可以使类去实现一个接口;实现接口就是使类满足接口的要求
7、属性的封装
- 定义一个person的类,现在属性是直接在对象中设置的,属性可以任意的被修改,可能会导致对象中的数据变的非常不安全
- TS可以在属性前面添加属性的修饰符
①public
修饰的属性可以在任意位置访问(修改)默认值
②private
私有属性,私有属性只能在类内部进行访问(修改);通过在类中添加方法使得私有属性可以被外部访问(getter 方法用来读取属性/setter 方法用来设置属性) - TS中设置getter方法的形式,用起来跟属性一样
get name(){return this._name ;
}
set name(value){this._name = value;
}
③protected
是包含的属性,只能在当前类和当前类的子类中使用
8、泛型
- 在定义函数或是类时,如果遇到类型不明确就可以使用泛型
//指定一个泛型T
function fn<T>(a: T): T{return a;
}
- 可以直接调用具有泛型的函数
let result1 = fn(10); //不指定泛型,TS可以自动对类型就行推断
let result2 = fn<string>('hello'); //指定泛型
- 可以t同时指定多个泛型
function fn2<T, K>(a: T, b: K): T{return a;
}
fn2<number, string>(a: 123, b: 'hello');interface Inter{length: number;
}
//T extends Inter 表示泛型T必须是Inter实现类(子类)
function fn3<T extends Inter>(a: T): number{return a.length;
}//在类中使用泛型
class MyClass<T>{name: T;constructor(name: T){this.name = name;}
}
const mc = new MyClass<string>('孙悟空');