typescript学习笔记

254 阅读5分钟

声明变量的写法

安装

npm i -g typescript

文件名以ts结尾,如果语法不对,编译器会报错

typescript中数据类型有number,string,boolean,字面量,any,unknown,void,never,object,array,tuple,enum等

声明变量

可以直接在变量后添加冒号注明类型,如果未注明且未赋值,类型默认为any

  let a:number;
  let b: string;
  let c:number=2;
  let d='22'//number
  let e;//any
 let f:string|number//表示f的类型可以是string也可以是number
 let g:{name:string}&{age:number}//表示g中既有name又有age,如`g={name:'mmc',age:1}`

字面量 :变量的类型为某个值的,如let a: 10;let b:"male"|"female" 如果某个变量可以是多种类型let c:boolean|string

let d;等价于let d:any;

let e:unknown any类型变量可以赋值给任意类型变量,unknown则会报错 unknown赋值给其它类型变量时,可以写成

let a:string;let b:unknown;let c:number;
if(typeof b==='number'){
    c=b
}
a=b as string
a=<string>b


声明函数

     //函数声明,括号后面的类型为函数返回值的类型,
     //当函数没有返回值时,为`void`,不写return,或return;return undefined;return null;
     //`function fn1():never{}`表示永远没有返回值,比如里边抛出错误
  function sum(a:number,b:number):number{
    return a+b
}
//先声明后赋值
let a:(b:number,c:number)=>number
a=function(n1:number,n2:number):number{
    return 11
}

对象声明

let a:{}
let b:{name:string}//b中必须有name并且只有name
let c:{name:string,age?:number}//c中必须有name,可能有age
let d:{name:string,[propName:string]:any}//d中必须有name,其它随意

数组声明

    let a:string[]
    a=['1','2']
    let b:Array<number>
    b=[1,2,3]

元组tuple,长度固定的数组

let a:[string,string,number]
a=['1','2',2]

枚举enum

enum Gender{
    Male=0,Female=1
}
let a:{name:string,gender:Gender}
a={
    name:'mc',gender:Gender.Male
}

类型别名

type mytype=1|2|3|4|5

let a:mytype

编译

单个编译tsc xxx.ts

单个持续编译tsc xxx.ts -w

编译后会生成对应的js文件,可以通过配置文件来决定生成文件的名字,目标文件夹等

或目录中新增tsconfig.json(可为空白{}),直接tsc便可编译当前目录所有ts文件,tsc -w同理.

tsconfig.json的一些配置

 //**代表任意文件夹,*代表任意文件,exclude表示排除选项,不需要编译的文件,
//extends,表示要继承的配置文件,
//files表示被编译的文件列表,一般文件少时会用到
//自己使用时不需要将所有写出来

{
    "include":[
       
        "./src/**/*"
    ],//要编译的目录
    “exclude”:[
        "./src/hello/**/*"
    ]"extends":"./config/base",
    “files”:[
    "xxx.ts","xx.ts"
    ],
	"compilerOptions":{
        //编译后的js的版本,默认ES3,ESNext表示默认最新,可以小写
        "target":"ES6",
        //module表示模块化的规范,es6,commonjs,none等
        "module":"es6",
        //lib指定项目中用到的库,一般情况不需要改,默认为dom
        "lib":["dom"],
        //outDir编译后的文件所在目录
        "outDir":"./dist",
        //outFile表示编译后合并为某个文件,module值需要为system
        "outFile":"./dist/app.js",
        "allowJs":false,//是否连js文件一起编译,默认false
        "checkJs":false,//是否检查js语法
        "removeComments":true,//是否移除注释
        "noEmit":true,//不生成编译后的文件,一般用来检查语法
        "noEmitOnError":true,//报错时不生成编译后的文件,没报错时正常生成
        "alwaysStrict":false,//编译后的文件是否为严格模式,默认false
        "noImplicitAny":true,//不允许隐式any,即必须声明类型
        "noImplicThis":false,//不允许不明确的this
        "strictNullChecks":true,//严格检查可能为null的变量的使用
        "strict":true,//所有严格检查的开关
        
        
    }
}

webpack使用

npm init -y生成package.json

cnpm i -D webpack-cli typescript ts-loader

1.编写webpack.config.js

    const path=require('path')
module.exports={
 mode:"development",
    entry:"./src/index.ts",//入口文件
    output:{
        path:path.resolve(__dirname,'dist'),//指定打包后的目录
        filename:"bundle.js"//打包后的文件名
    },
    module:{//指定打包时要使用的模块
        //指定规则
        rules:[
            {
                test:/\.ts$/,
                use:'ts-loader',
                exclude:/node-modules/
                //表示使用ts-loader去编译以.ts结尾的文件,并且排除node-modules目录下的文件
            }
        ]
    }
}

2.创建tsconfig.json

3.在package.json中添加script命令

"build":"webpack"

然后npm run build执行打包


一些插件

cnpm i -D html-webpack-plugin

安装一个自动生成html的插件

//继续在webpack.config.js中
const HTMLWebpackPlugin=require('html-webpack-plugin`')

plugins:[//配置插件
    new HTMLWebpackPlugin({
        title:"网页title"template:"./src/index.html"
        //不加template则生成默认的index.html,加上的话需要自己创建index.html,打包后会以这个为模板生成index.html
    }),
]

使用内置服务器

cnpm i -D webpack-dev-serve

然后在package.json中添加scripts命令

"start":"webpack serve --open"

然后使用npm start


上面打包dist时不会先删除dist文件,安装插件使每次打包前先删除dist

cnpm i -D clean-webpack-plugin

使用方法同上

const {CleanWebpackPlugin}=require('clean-webpack-plugin')
plugins:[//配置插件
    new CleanWebpackPlugin(),
]

当有一个test.ts文件 如果引入时是import {test} from './test' 则需要在webpack.config.js中配置

resolve:{
    //表示ts和js文件引入时可以不写后缀名,表示引用模块而不是整个文件
    extensions:['.ts','.js']
}


如果要兼容一些低版本浏览器

cnpm i -D @babel/core @babel/preset-env babel-loader core-js

然后在webpack.config.js中配置rules

{
                test:/\.ts$/,
                    //会先用后面的ts-loader编译ts文件,再用babel编译
              // use:['babel-loader','ts-loader'],或者
              use:[
              {
              loader:"babel-loader",
              //进行一些babel配置
              options:{
              presets:[
              	//设置预定义的环境
              	//指定环境的插件
              	["@bable/preset-env",{
              		//要兼容的目标浏览器
              		targets:{
              			"chrome":"88",
              			//"ie":"11"
              		},
              		//指定corejs的版本
              		"corejs":"3",
              		"useBuiltIns":"usage",//使用corejs的方法,usage表示按需加载
              	}]
              ]
              }
              },'ts-loader'
              ],
                exclude:/node-modules/
                
            }

如果想要webpack兼容ie,在output里面配置 environment:{arrowFunction:false}表示编译后的代码不使用箭头函数

class Person{
    name:string;
    age:number;
    constructor(name:string,age:number){//构造函数
        this.name=name
        this.age=age
    }
    // name:string="mmc"
    // static age:number=19
    // readonly color:string="red"
    // static readonly height:string="111"
    sayHellow(){//实例方法

    }
    static sayNo(){//类方法

    }
}
const p1=new Person('mmc',2)
//实例属性p1.name,类属性Person.age
//继承
class Teacher extends Person{
    // 如果子类中要写constructor,重写方法,则必须调用super() 表示调用父类构造函数

}

抽象类

抽象类,如父类不想被用来new,可以abstract

抽象类可以添加抽象方法,抽象方法没有方法体,子类必须重写抽象方法

    abstract class Animal{
    abstract sayHellow():void;
}

接口

接口,用来定义一个类的结构

可以重复定义,重复定义会融合,而不是覆盖

接口中所有属性都不能有值

interface doctor{
    name:string;
    age:number;
    sayHello():void;
}
const obj:doctor={
    name:'mmc',
    age:23,
    sayHello(){}

} 
// 用类实现接口,里面的属性要满足接口的要求
class doc1 implements doctor{
    name:'s'
    age:1
    sayHello(): void {
        
    }
}

属性的封装

ts可以在属性前加修饰符

private私有属性只能在类中访问,实例无法访问,继承的类中也无法访问

protected可以被继承的私有属性

class move{
    private speed:number
    private _way:string
    constructor(public name:string){

    }
    getSpeed(){
        return this.speed
    }
    addSpeed(value:number){
        this.speed+=value
    }
    get way(){
        return this._way
    }
    set way(val){
        this._way=val
    }

}
const move1=new move('2')
move1.way
move1.way='www'

泛型

定义函数时遇到类型不明确时

function test<T>(a:T):T{
    //表示函数参数和返回值类型相同
    return a
}
test(1)
test('dd')
test<string>('ssss')//指定泛型
function test2<T,K>(a:T,b:K):T{
return a
}
interface Inter{
    len:number
}
//表示泛型T需要实现Inter接口
function fn2<T extends Inter>(a:T):number{
return a.len
}