一.TS是什么?
TypeScript 是 JaveScript 类型的超集,它可以编译成纯 JavaScript,TypeScript 可以在任何浏览器、任何计算机和任何操作系统上运行,并且是开源的。
二.TS和JS的异同
TypeScript 支持与 Javascript 几乎相同的数据类型,此外还提供了使用的枚举类型,TypeScript 支持的类型包括:布尔值、数字、字符串、数组、元组、枚举、Any、Void、Null、 Undefined、Nerver、Object、类型断言。
三.如何将TS编译为JS
npm i typescript -g (全局安装TS)
tsc demo.ts (tsc运行TS文件,此时会生成demo.js文件)
node demo.js (运行js文件)
四.如何简化执行TS代码
npm i ts-node -g (全局安装ts-node)
ts-node demo.ts
五.TS的类型注解
类型注解
作用:相当于强类型语言中的类型声明,可以对变量起到约束作用。由我们来告诉TS变量是什么类型。
语法:(变量/函数):typeName
类型推断
作用:TS会自动的尝试去分析变量的类型。
注意:如果TS能够自动分析变量的类型,我们就什么也不用做。反之,如果TS无法分析变量的类型的话,我们则需要使用类型注解。
写TS就是希望每一个变量和属性的类型都是固定的。想让类型固定有两种方式:类型推断和类型注解。能推断就推断,推断不出来的我们来告诉它。
1.字面量
let color :‘red‘ |’blue‘|’black‘;
let num : 1 |2|3
let type:number|string
这里的color的值只能是red,blue,black中的一个,num的值也只能是1,2,3里面的一个,type的值可以是number类型或者string类型
2.any
let a : any = 4
a='hello'
a=true
3.unknown
let b : unknown =4
b = 'hello'
any和unknown的区别:
any在编译阶段跳过类型检查(适用于已有代码的改写),unknown只是不确定数据类型,但是要想使用数值的方法,必须确定数据类型(比any更加安全)
如何处理unknown:
1.if判断:if(type of e === 'string'){}
2.类型断言:s = e as string
或者s=<string>e
4.void
let unusable : void = undefined
void类型的值多用于函数,表示函数没有返回值,例:
function noreturn():void{
alert('this is not return')
}
5.never
function error (message : string):never{
throw new Error (message)
}
never表示函数永远不会有返回结果,多用于抛出错误
6.object
(1) let obj : object = {}
很少用
(2)let b : {name : string}
表示必须包含name的属性,且不能包含除name以外的其他属性
(3)let c : {name : string , age ? : number}
在属性名后加?表示这个属性可选
(4)let d : {name : string , [ XXX: string] : any}
表示这个对象里面可以添加其他任意属性,XXX可以自定义名字
7.array
let e : string[]
表示希望e为数组,且e中全部存的为字符串
let f :number[]
或者 let f :Array
表示希望f为数组,且f中全部存的为数字,其中第二种方法<>里面可以自定义校验
8.tuple
let h : [string , string]
表示h里面只能存两个值,且都是string类型
9.enum
先定义枚举
enum color {
red
green
blue
}
let c : color = color.green
类型别名:
语法:type 类型名称 = { name: string, age: number }
type User = {name:string,age:number}
const ObjectArr:User[] = [{
name:'anny',
age:18
}]
或者是联合类型相结合
type myType = 1|2|3|4|5
六.TS的配置文件
1.在终端中执行tsc -w表示监视所有的ts文件,若文件发生变动,则会自动生成新的js文件
2.创建tsconfig.json文件,它是ts编译器,ts编译器可以根据它的信息对代码进行编译
//1.include:用来指定哪些ts文件需要被编译
"include": [
"./src/**/*" //表示编译src目录下的所有ts文件 /**表示任意目录 /*表示任意文件
]
//2.exclude:用来指定哪些文件不需要被编译
"exclude": [
"./src/hello/**/*" //表示排除src下hello下所有的ts文件
]
//3.extends:表示当前json文件下需要继承其他json文件的配置
"extends": "./config/base" //表示当前json文件下自动包含config目录下base.json中所有的配置信息
//4.files:指定被编译文件列表,只有需要编译的文件少的时候才会用到
"files": [
"core.ts"
"type.ts"
]
//5.compilerOptions:编译选项是配置文件中非常重要的也是比较复杂的配置选项,在compilerOptions中包含多个子选项,用来完成对编译的配置
"compilerOptions": {
"target": "es3" //指定ts被编译的js版本,可选的值:es3,es5,es6,es2015,es2016,es2017,es2018,es2019,es2020,esnext (表示最新版本)
"module": "es2015" // 指定要使用的模块化规范,可选的值:none,commonjs,amd,system,umd,es6,es2015,es2020,esnext
"lib": [] //指定项目中要使用的库(一般不用改,若不在浏览器中运行,在nodejs中运行,则要做一些配置)
"outDir": "./dist" //指定编译后文件所在的目录
"outFile": "./dist/app.js" //用来将所有的ts文件合并成一个文件,所有的全局作用域中的代码会合并到一个文件中
"allowJs": false //是否对js文件进行编译,默认false
"checkJs": false //是否检查js代码符合语法规范,默认false
"removeComments": false //是否移除注释,默认false
"noEmit": false //不生成编译后的文件,默认false
"noEmitOnError": false //当有错误时,不生成编译后的文件,默认false
}
七.接口:interface
语法: interface 类型名称 { name: string }
用法: 用于定义通用类型的集合。
//参数规范
interface AjaxOptions{
url:string,
type:string,
data:object,
success(data:object):void
}
//ajax函数
function ajax(options:AjaxOptions){
}
//调用
ajax({
url:'http://www.baidu.com',
type:'get',
data:{},
success(data){
}
})
可选属性
给属性加了问号之后就表示这个属性可传可不传
interface config{
color?:string;
width:number;
}
只读属性
如果一个interface接口中的数据是只读的,不想被人修改,那么我们可以在接口的属性前面加一个 “readonly” 关键字即可。
interface Point{
readonly x:number,
y:number
}
let poi:Point={
x:100,
y:200
}
// poi.x=110 错误,上面加了readonly就不可以重新赋值
额外属性检查
interface Point{
readonly x:number,
y:number,
[propName:string]:any //接口额外属性,就是告知接口规范:我可能有别的其它属性和值,请忽略掉
}
let poi2:Point={
x:100,
y:200,
z:300 //额外的属性和值
}
函数类型的接口
interface SumInterFace{
(a:number,b:number):number
}
let sum:SumInterFace=function (a:number,b:number) {
return a+b
}
与type(类型别名)的区别:
interface只能用于代表对象或函数,而类型别名type可以代表其他类型的值,例如:
interface Person {
name:string
}
type:Person1 = string
typecript通用性规范: 如果能用接口表述一些类型时,尽量用接口,实在没办法再用类型别名
八.类:class
1.类成员的访问修饰符
什么是访问修饰符?
指的就是可以在类的成员前通过关键字来设置当前成员的访问权限.
权限有三种:
public:公开的,默认
private:私有的,只能在当前类中进行访问
protected:受保护的,只能在当前类或者子类中进行访问
(1)public在公开修饰符里,下面三种情况color都可以访问
enum Color {
red = 'red',
yellow = 'yellow'
blue = 'blue'
}
class Car{
//不加访问修饰符,默认是公开的
color:string
constructor(){
this.color = Color.red
}
}
let byd=new Car()
// byd.color 可以访问
class Audi extends Car{
sayHi(){
console.log(this.color); //可以访问
}
}
let audi=new Audi()
// audi.color可以访问
(2)private私有的:只能在当前类中使用
class Car {
constructor() {
this.run() //可以使用,加了private后只能在当前类中使用
}
//加了private,就只能在当前类中使用
private run() {
console.log("车跑了");
}
}
let byd = new Car()
class Audi extends Car {
sayHi() {
this.run() //不可以访问
}
}
let audi = new Audi()
audi.run() //不可以使用
(3)protected:protected和private类似,但是,protected成员在派生类中可以访问
class Car {
constructor() {
this.run() //可以使用
}
protected run() {
console.log("车跑了");
}
}
let byd = new Car()
byd.run() //不在当前类,不可以访问
class Audi extends Car {
sayHi() {
this.run() //可以使用
}
}
let audi = new Audi()
audi.run() //不在当前类,不可以访问
2.类的只读属性和类中构造函数参数简写
(1)只读属性:只能访问不能修改(一样在前面加readonly)
class Cat{
readonly name:string
constructor(){
this.name="加菲"
}
//说明:在ts中,类的属性必须要在声明的时候赋值,或者在构造函数中赋值(真实值或参数都可以),否则会报错
}
var cat =new Cat()
cat.name;
cat.name="新名" //只读属性,不可以修改
(2)类中构造函数参数简写
/*
class Cat {
type: string
constructor(type: string) {
this.type = type
}
}
var cat = new Cat("加菲")
*/
//上面简写
class Cat {
constructor(public type: string) {
}
}
var cat = new Cat("加菲")
//也就是参数前面加一个public就等于写了type:string和this.type=type这两行代码
3.类的成员存取器
普通给类成员赋值:
class People{
name:string=""
}
var p=new People()
p.name="我是很长的名字"
但是发现名字无法限制,于是我们采用另一种方法:类成员存取器,它的作用是可以将类中接收到的属性值进行限制,具体如下:
class People{
_name:string=""
get name(){
return this._name
}
set name(value:string){
//这里可以做限制
if(value.length<2 || value.length>5){
throw new Error("名字不合法")
}
}
}
var p =new People()
p._name="我是很长的名字"
4.类类型接口
TypeScript能够用它来明确的强制一个类去符合某种契约
实现(implements)是面向对象中的一个重要概念。一般来讲,一个类只能继承自另一个类,有时候不同类之间可以有一些共有的特性,这时候就可以把特性提取成接口(interfaces),用 implements 关键字来实现。这个特性大大提高了面向对象的灵活性,例:
interface Alarm {
// 定义一个公用的方法,具体的实现在实现的类里面去实现
warning():void;
}
class Door implements Alarm {
warning() {
console.log('门报警器');
}
}
class Car implements Alarm {
warning() {
console.log('车报警器');
}
}
class Baoma extends Car implements Alarm {
warning() {
console.log('宝马车报警器');
}
}
这个案例里面 车和门都有报警功能,所以将这个公共的功能抽离出来封装为一个接口
需要这个功能的类比如Car Door Baoma 等去实现这个接口 implements即可
要注意的是在接口里面是方法的签名,在类里面进行方法体的实现
let d1 = new Door();
let c1 = new Car();
let b1 = new Baoma();
d1.warning();
b1.warning();
这个打印只有两个属性; warning这个方法是绑定在构造函数Baoma的原型对象prototype上面的,可以在浏览器里面查看
console.log(b1);
5.接口继承接口
//接口继承接口(支持多继承)
interface TwoDPoint{
x:number,
y:number
}
interface ThreeDPoint {
z:number
}
interface FourDPoint extends ThreeDPoint,TwoDPoint{
time:Date
}
let poi3:FourDPoint={
x:100,
y:200,
z:300,
time:new Date()
}
6.接口继承类
class Bird{
type:string="画眉鸟",
fly():void{
}
}
interface Fly extends Bird{
}
let f2:Fly={
type:"啄木鸟",
fly():void{
}
}