内置对象JavaScript中有很多内置对象,它们可以直接在TypeScript中当做定义好了的类型。内置对象是指根据标准在全局作用域(Global)上存在的对象。这里的标准是指ECMAScript和其他环境(比如DOM)的标准。ECMAScript的内置对象Boolean、Number、String、Date、RegExp、Errorletb:Boolean=newBoolean(1)letn:Number=newNumber(true)lets:String=newString('abc')letd:Date=newDate()letr:RegExp=/^1/lete:Error=newError('errormessage')BOM和DOM的内置对象Window、Document、HTMLElement、DocumentFragment、Event、NodeListconstdiv:HTMLElement=document.getElementById('test')constdivs:NodeList=document.querySelectorAll('div')document.addEventListener('click',(event:MouseEvent)=>{console.dir(event.target)})constfragment:DocumentFragment=document.createDocumentFragment()
声明文件在使用第三方库时,第三方库有很多的全局变量,在使用TypeScript时,TypeScript不知道这些全局变量,就会报错,智能提示也不好比如在平常使用jQuery时,直接在<script>标签引入jQuery就会有$或jQuery了,但在TypeScript中就不知道//安装jQuery:npminstalljquery//导入jqueryimport{jQuery}from"jquery";jQuery('#foo')#就会报错就需要使用declarevar定义它的类型declarevar并没有真的定义一个变量,只是定义了全局变量jQuery的类型,仅仅会用于编译时的检查,在编译结果中会被删除。import{jQuery}from"jquery";declarevarjQuery:(selector:string)=>any;jQuery('#foo');手动定义声明文件声明文件名字格式:xxx.d.ts,TS编译器会自动去扫描这类文件创建jQuery.d.ts把下面这句从上面独立出来declarevarjQuery:(selector:string)=>any;缺点:这么多库,这么多全局变量,不可能自己加,所以这些都提供有自己的声明文件下载库自己的声明文件很多的第三方库都定义了对应的声明文件库,库文件名一般为@types/xxx可以在https://www.npmjs.com/package/package进行搜索有的第三库在下载时就会自动下载对应的声明文件库(比如:webpack),有的可能需要单独下载(比如jQuery/react)//下载jQuery声明文件npminstall@types/jquery--save-dev
说明泛型的使用:当定义类型时(函数、变量、接口、类),只有在使用的时候,才只是具体是什么类型时,就可以使用泛型定义引入实现生成传入指定元素,指定长度的数组functioncreatArray(value:any,count:number):any[]{letarr:any[]=[];//需要初始化for(leti=0;i<count;i++){arr.push(value);}returnarr;}console.log(creatArray('XX',5))//['XX','XX','XX','XX','XX']使用泛型functioncreatArray<T>(value:T,count:number):T[]{letarr:T[]=[];//需要初始化for(leti=0;i<count;i++){arr.push(value);}returnarr;}console.log(creatArray<number>(22,5))//[22,22,22,22,22]多个泛型参数的函数泛型常用字母K、V、TfunctioncreatArray<K,V>(x:K,y:V):[K,V]{return[x,y]}console.log(creatArray<number,string>(22,'XX'))//[22,'XX']泛型接口在实现接口时,再定义类型//泛型接口interfaceIbaseCRUD<T>{data:T[]add(t:T):voidgetById(id:number):T}classUser{id?:number;//id主键name:string;age:number;constructor(name:string,age:number){this.name=name;this.age=age;}}classUserCRUDimplementsIbaseCRUD<User>{data:User[]=[]add(user:User):void{user={...user,id:Date.now()}this.data.push(user);console.log('saveuser',user)}getById(id:number):User{returnthis.data[id]}}constuserCRUD=newUserCRUD()userCRUD.add(newUser('XX',16))userCRUD.add(newUser('YY',17))console.log(userCRUD.getById(1))//{name:'YY',age:17,id:1646630710525}泛型类在实例化类时,再定义类型classUser{name:string;age:number;constructor(name:string,age:number){this.name=name;this.age=age;}}classUserCRUD<T>{data:T[]=[]add(user:T):void{this.data.push(user);console.log('saveuser',user)}}constuserCRUD=newUserCRUD<User>();userCRUD.add(newUser('XX',16))//saveuserUser{name:'XX',age:16}泛型约束当使用泛型时,函数逻辑中,可能并不知道该类型有这个方法或属性,而报错,智能提示也不好functionfn<T>(x:T):void{//console.log(x.lenght)//报错:类型“T”上不存在属性“lenght”。}处理:泛型继承某类、某接口一个泛型变量只能继承一个类或者接口classUser{constructor(publicname:string,publicage:number){}}//泛型继承User类functionfn<TextendsUser>(x:T):void{console.log(x.name,x.age)}//传入符合这中类型的值fn(newUser('XX',16))//XX16
函数函数的参数和返回值是可以定义的类型的//命名函数functionfun(x:number,y:number):number{returnx+y;}//匿名函数letlo=function(msg:string):void{//viod表示没有返回值console.log('匿名函数')}可选参数&默认参数可选参数?关键字functionadd(x:number,y:number,flag?:boolean):number{if(flag){returnx+y;}else{returnx-y;}}console.log(add(5,3,true));//8console.log(add(5,3));//2默认参数functionadd(x:number,y:number=3,flag?:boolean):number{if(flag){returnx+y;}else{returnx-y;}}console.log(add(5,3));//2console.log(add(5));//2剩余参数在Python、Java里叫不定长参数functionadd(x:number,...args:number[]):number{console.log(x,args)//5[4,3,2,1]args.forEach(num=>{x+=num;});returnx;}console.log(add(5,4,3,2,1));//15函数重载Java的重载,是函数名一样,参数列表不一样,而TypeScript有点不一样函数参数定义有类型断言,声明重载,规范传入参数的类型//重载函数声明。相对于规范传入参数的类型functionadd(x:string,y:string):string;functionadd(x:number,y:number):number;functionadd(x:number|string,y:number|string):number|string{if(typeofx==="number"&&typeofy==="number"){returnx+y;//数字类型相加}if(typeofx==="string"&&typeofy==="string"){returnx+'+'+y;//字符串拼接}}console.log(add('**','**'))//**+**console.log(add(3,5))//8
说明对于传统的JavaScript程序我们会使用函数和基于原型的继承来创建可重用的组件,但对于熟悉使用面向对象方式的程序员使用这些语法就有些棘手,因为他们用的是基于类的继承并且对象是由类构建出来的。从ECMAScript2015,也就是ES6开始,JavaScript程序员将能够使用基于类的面向对象的方式。使用TypeScript,我们允许开发者现在就使用这些特性,并且编译后的JavaScript可以在所有主流浏览器和平台上运行,而不需要等到下个JavaScript版本。类的结构类的主要元素:属性、构造器、方法classCat{//属性name:stringage:number//构造函数constructor(name:string,age:number){this.name=name;this.age=age;}//普通方法eat():void{console.log(`${this.name}吃玉米`)}}letcat:Cat=newCat('O_O',12);cat.eat()继承&多态关键字extendsclassAnimal{//属性name:stringage:numberconstructor(name:string,age:number){this.name=name;this.age=age;}run(distance:number):void{console.log(`Animalrun${distance}m`)}}classCatextendsAnimal{//继承type:string//构造函数constructor(name:string,age:number){super(name,age)//调用父类构造函数}//普通方法eat():void{console.log(`${this.name}吃玉米`)}//重写父类方法run(distance:number):void{console.log(`${this.name}run${distance}m`)}}letcat:Cat=newCat('O_O',12);cat.run(15)权限修饰符默认公共public,实例对象,类内部,子类都可以访问私有private,只有类内部可以访问保护protected,类内部、子类之类可以访问classAnimal{//属性protectedname:string//当前类内部子类publicage:number//公共constructor(name:string,age:number){this.name=name;this.age=age;}run(distance:number):void{console.log(`Animalrun${distance}m`)}}classCatextendsAnimal{//继承privatetype:string//当前类内部//构造函数constructor(name:string,age:number){super(name,age)//调用父类构造函数}//普通方法eat():void{console.log(`${this.name}吃玉米`)}//重写父类方法run(distance:number):void{console.log(`${this.name}run${distance}m`)}}letcat:Cat=newCat('O_O',12);cat.run(15)console.log(cat.age)//12readonly修饰符readonly修饰属性为可读,只能在定义时或者构造函数初始化classPerson{readonlyname:string='abc'constructor(name:string){this.name=name}}letjohn=newPerson('John')参数属性TypeScript不一样的地方,作用简化代码不止能写readonly,其他权限public,private,protected//与上一个代码效果一样classPerson{constructor(readonlyname:string){}}letjohn=newPerson('John')静态属性不用实例化就能获取的属性classDog{staticname_:string='O_O'}console.log(Dog.name_)//'O_O'抽象类抽象类和抽象方法用abstract关键字抽象类作为其它类继承使用。抽象类不能被实例化。不同于接口,抽象类的普通方法可以有方法体,但抽象方法不能有方法体抽象方法必须在抽象类里abstractclassAnimal{abstracteat():void;//抽象方法没有实现细节run(x:number){//继承后普通方法可以不用实现console.log(`xxrun${x}m`)}}classDogextendsAnimal{eat(){//必须实现全部抽象方法的方法体console.log(`dogeatxx`)}}letdog:Dog=newDog()dog.run(15)//xxrun15m
接口说明接口是对象的状态(属性)和行为(方法)的抽象(描述),简单理解就是规范结构,接口不能初始化属性TypeScript的核心原则之一是对值所具有的结构进行类型检查。我们使用接口(Interfaces)来定义对象的类型。接口结构结构关键字interfaceinterfaceIPersion{id:numbername:stringage:string}constperson:IPersion={id:1,name:'o_o',age:14};可选属性interfaceIPersion{id:numbername:stringage?:string//该属性可以不存在}constperson:IPersion={id:1,name:'o_o'};只读属性关键字readonly该值只能在初始化时被改变,除此之外不能被改变interfaceIPersion{id:numberreadonlyname:string//只读age?:number}letperson:IPersion={id:1,name:'o_o'};person.id=2;//person.name='*_*';//报错不呢被改变readonlyvsconstreadonly修饰属性const修饰变量接口规范函数类型看着可能有点奇怪,这里明确一个概念,函数的必要元素:参数列表、返回值。(匿名没有函数名,所以函数名非必要)//定义函数类型interfaceIFunType{//参数列表:返回值(s1:string,s2:string):string}//变量类型为函数letfun:IFunType=function(s1:string,s2:string):string{return`${s1}_${s2}`}console.log(fun('kk','xx'));类接口作用于Java、C#里面一样,类需要实现接口interfaceIAnimal{type:stringeat():void}classCatimplementsIAnimal{type:string='猫'eat(){console.log(`${this.type}吃${this.type}粮`)}}letcat:Cat=newCat();cat.eat()接口继承接口接口间叫继承interfaceIAnimal{//动物接口type:stringeat():void}interfaceIFelidaeextendsIAnimal{//猫科接口继承动物接口leg_num:number}类实现多个接口interfaceIAnimal{//动物接口type:stringeat():void}interfaceIPerson{name:stringage:number}classPersonimplementsIAnimal,IPerson{type:string='person'name:stringage:numbereat(){console.log(`${this.type}吃玉米`)}}letperson:Person=newPerson();person.eat()//person吃玉米
说明TypeScript支持与JavaScript几乎相同的数据类型,此外还提供了实用的枚举类型布尔值letmsg:boolean=true;数字TypeScript里的所有数字都是浮点数。这些浮点数的类型是number。letn1:number=12;//十进制letn2:number=0b1010;//二进制letn3:number=0o12;//八进制letn4:number=0xa;//十六进制字符串单引号双引号都可以lets:string='xxx';undefined和null它们的本身的类型用处不是很大letund:undefined=undefined;letnu:null=null;数组TypeScript像JavaScript一样可以操作数组元素。有两种方式可以定义数组。第一种,let变量名:类型[]=[];letarr:number[]=[1,2,3,4];第二种泛型定义,Array<类型>letarr:Array<number>=[1,2,3,4];元组元组类型允许表示一个已知元素数量和类型的数组lettu:[number,string,boolean]=[1,'咪咪',true];枚举enum类型是对JavaScript标准数据类型的一个补充enumColor{Red,//0Green=10,Blue//11}letcolor:Color=Color.Blue;console.log(Color)//0any当不知定义什么类型比较合适时使用leta:any;a=12;a='12';letb:any=12;b='a';console.log(a,b)//'12''a'object所有对象的基类leto:object={'a':12};letoo:object=newString('oo');联合类型表示取值为多种类型中的一种functionfun(s:number|string):number|string{returns}类型断言当使用联合类型时,编译器可能不知道,现在我们处理的时候什么类型,而出现报错,因此就需要告诉编译现在处理的是什么。/*两种定义方式:第一种:(<类型>变量)第二种:(变量as类型)*/functionfun(s:number|string):number{//返回参数的长度if((<string>s).length){return(<string>s).length;}else{return(sasnumber).toString().length;}}类型推断当不定义类型是,TypeScript会自动推断类型,如果只是定义,不初始化变量,则类型为anyletn=123;//推断类型为number//n='a';//报错letm;//推断类型为anym=12;m='a';
生成package.json文件终端运行npminit-ypackage.json文件{"name":"code","version":"1.0.0","description":"","main":"index.js","scripts":{"test":"echo\"Error:notestspecified\"&&exit1"},"keywords":[],"author":"","license":"ISC",}生成tsconfig.json文件终端运行,生成ts配置文件tsc--init创建html文件新建目录public创建html文件index.html<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>Document</title></head><body></body></html>创建ts文件新建目录src创建ts文件main.ts(()=>{alert('打包成功啦~~~~')})()创建webpack.config.js文件新建目录./build创建Js文件webpack.config.jsconst{CleanWebpackPlugin}=require('clean-webpack-plugin')constHtmlWebpackPlugin=require('html-webpack-plugin')constpath=require('path')constisProd=process.env.NODE_ENV==='production'//是否生产环境functionresolve(dir){returnpath.resolve(__dirname,'..',dir)}module.exports={mode:isProd?'production':'development',//生产环境还是开发环境entry:{app:'./src/main.ts'//程序主目录},output:{//打包输出配置项path:resolve('dist'),//打包结果在dist目录下filename:'[name].[contenthash:8].js'//打包后的js文件名格式},module:{rules:[{//对src目录下的ts文件编译操作test:/\.tsx?$/,use:'ts-loader',include:[resolve('src')]}]},plugins:[newCleanWebpackPlugin({//把以前打包的js清除}),newHtmlWebpackPlugin({template:'./public/index.html'//当前目录的html打包})],resolve:{extensions:['.ts','.tsx','.js']//引入这类文件可以不写扩展名},devtool:isProd?'cheap-module-source-map':'eval-cheap-module-source-map',//提示错误信息devServer:{host:'localhost',//主机名port:8081,open:true//自动打开浏览器},}下载依赖npminstall-Dtypescriptnpminstall-Dwebpackwebpack-cliwebpack-dev-server//打包html和清除之前打包的jsnpminstall-Dhtml-webpack-pluginclean-webpack-plugin//对ts文件进行编译处理npminstall-Dts-loader#涉及跨平台的命令npminstall-Dcross-env配置打包命名//开发环境打包"dev":"cross-envNODE_ENV=developmentwebpack-dev-server--configbuild/webpack.config.js",//生产环境打包"build":"cross-envNODE_ENV=productionwebpack--configbuild/webpack.config.js"运行打包//开发环境打包测试npmrundev//生产环境打包npmrunbuild开发环境打包生产环境打包
什么是TypeScriptTypeScript是一种由微软开发的开源、跨平台的编程语言。它是JavaScript的超集,最终会被编译为JavaScript代码。2012年10月,微软发布了首个公开版本的TypeScript,2013年6月19日,在经历了一个预览版之后微软正式发布了正式版TypeScriptTypeScript的作者是安德斯·海尔斯伯格,C#的首席架构师。它是开源和跨平台的编程语言。TypeScript扩展了JavaScript的语法,所以任何现有的JavaScript程序可以运行在TypeScript环境中。TypeScript是为大型应用的开发而设计,并且可以编译为JavaScript。TypeScript是JavaScript的一个超集,主要提供了类型系统和对ES6+的支持,它由Microsoft开发,代码开源于GitHub上TypeScript三大特点始于JavaScript,归于JavaScriptTypeScript可以编译出纯净、简洁的JavaScript代码,并且可以运行在任何浏览器上、Node.js环境中和任何支持ECMAScript3(或更高版本)的JavaScript引擎中。强大的类型系统类型系统允许JavaScript开发者在开发JavaScript应用程序时使用高效的开发工具和常用操作比如静态检查和代码重构。先进的JavaScriptTypeScript提供最新的和不断发展的JavaScript特性,包括那些来自2015年的ECMAScript和未来的提案中的特性,比如异步功能和Decorators,以帮助建立健壮的组件TypeScript快速上手安装TypeScript首选安装好node环境下载地址:https://nodejs.org/zh-cn/命令行运行如下命令,全局安装TypeScriptnpminstall-gtypescript安装完成后,在控制台运行如下命令,检查安装是否成功tsc-VTypeScript程序src/main.ts(()=>{functionhello(name:string){return"你好啊!"+name;}console.log(hello('NoNo'))})()手动编译手动编译,因为是.ts文件,文件不能被浏览器运行,需要编译成js文件在终端中打开,输入tscmain.ts,自动生成编译好的mian.js文件vscode自动编译命令行生成配置文件tsconfig.jsontsc--init修改tsconfig.json配置"outDir":"./src",//指定编译输出目录"strict":false,//关闭严格模式依次点击启动监视任务,当文件保存了改变,就会自动编译终端->运行任务->所有任务->监视tsconfig.json类型注解TypeScript的带来的高级功能//基本类型的注解functionhello(name:string){return"你好啊!"+name;}接口实现复杂注解使用接口,实现复杂注解interfacePerson{firstName:string,lastName:string}functionhello(name:Person){return"你好啊!"+name.firstName+'·'+name.lastName;}letuser={firstName:'No',lastName:'No'}console.log(hello(user))类TypeScript支持JavaScript的新特性,比如支持基于类的面向对象编程。classPerson{firstName:string//属性lastName:string//构造函数constructor(firstName:string,lastName:string){this.firstName=firstNamethis.lastName=lastName}}functionhello(name:Person){return"你好啊!"+name.firstName+'·'+name.lastName;}letuser=newPerson('No','No')console.log(hello(user))