Learining TypeScript (一) TypeScript 简介 node
1. 设计目标 2 typescript
一、类型 7 数组
二、变量、基本类型和运算符 8 浏览器
三、流程控制语句 12 服务器
四、函数 12 架构
1、TypeScript出现的背景
在过去的几年里,基于JavaScript的Web应用的数量呈几何级数增加,虽然目前ES6(即ECMAScript2015,从ES6开始采用年份命名)的标准在2015年6月份已经发布了,增添了许多新的特性,例如:模块和类,以及一些实用的特性,例如Map,Sets,Generates,Promises等等,支持向后兼容,全部的老代码也能够正常运行,但目前为止尚未一个彻底支持ES6标准的JavaScript代理,不管是浏览器仍是服务器环境,因此开发者不得不将ES6代码向ES5转义,因此ES6标准的普遍应用,还须要一个漫长的过程。
为了解决JavaScript的维护和扩展问题,微软花了两年的时间开发出TypeScript,并在2012年10月公布了第一个公开的版本。它是JavaScript的一个超集,它与现存的JavaScript代码有很是高的兼容性,任何合法的JavaScript程序都是合法的TypeScript程序,另外它还给大型项目提供一个构建机制,TypeScript(如下简称ts)中加入了基于类(Class)的对象、接口和模块,采用面向对象编程的方式。至此ts就诞生了。
2、TypeScript的架构
学习的过程就是这样,当你学习一门新的东西的时候,老是要从基础知识开始学起,这样有利于你之后的学习,还有个做用是,给你之后的面试提供很大的帮助。
一、设计目标
咱们能够从如下几点中了解到,决定TypeScript做为程序语言发展到今天这个形态的设计目标和架构:
ts在编译时默认使用ES3标准进行编译,极大的提升了浏览器的兼容性,固然它也支持ES5和ES6的标准。通常状况下使用任意受支持的编译目标,咱们均可以使用ts特性,但部分特性须要ES5或更高的版本版本做为编译目标的先决条件。
二、TypeScript组件
TypeScript语言内部主要被分为三层,每一层又被依次分为子层或者组件,以下图所示:
每一层都有不一样的用途:
3、TypeScript语言特性
在介绍TypeScript语言特性以前,首要任务是要搭建开发环境,官方提供了一个在线编辑器http://www.typescriptlang.org/play/ 该编辑器以下图所示:
编辑器左侧编写TypeScript代码,右侧会自动编译成JavaScript代码,固然做为咱们专业的programmer来讲,不多会采用这种在线编辑的方式进行开发了,能够下载安装TypeScript的编译器,做为一个.Net Developer来讲,咱们能够时候用Visual Studio,从VS2015开始,自动集成了TypeScript的开发环境,若是是如下版本,须要去官方下载TypeScript插件,固然咱们如今推荐你使用VS2017了。除了这些以外,若是想在其余操做系统中开发,OSX和Linux,那咱们能够选择一些比较流行的编辑器,他们都会有TypeScript插件,好比Visual Studio Code(如下成为VS Code),Sublime等,这里我推荐VS Code,它较Visual Studio不一样在于前者是IDE集成开发环境,然后者定义为Eidtor(编辑器),咱们不须要去安装Visual Studio几十个G的安装包,并且VS Code已经提供了成千上万的插件供你使用,你本身也能够去开发本身的插件,如图所示:
微软大大一直以来都是那么的贴心。VS Code提供了各操做系统的版本,能够直接下载使用。
选择好咱们的开发编辑器后,就要安装TypeScript,须要用到npm命令,可是在使用npm命令前,须要在开发环境中安装node.js,地址https://nodejs.org,找到对应的版本下载便可。验证是否安装成功,可以使用
npm –version 查看npm版本
下面咱们可使用命令安装TypeScript了
npm install -g typescript
(-g)为全局安装,可是若是你是OS X用户,须要使用sudo命令,须要获取管理员权限,
sudo npm install -g typescript
可使用 tsc -v 命令验证是否安装成功
Ok,至此咱们的开发环境就搭建完成了。
如今咱们建立一个test.ts文件,保存一个文件夹内,里面输入如下代码:
var t : number = 1;
而后切换到此文件夹内,执行
tsc test.ts
此时能够发现,在同目录下,会编译生成一个test.js文件。如图:
一、类型
咱们已经知道,ts是js的超集,ts经过向js增长可选的静态类型声明来把js变成强类型语言,可选的静态类型声明可约束函数,变量,属性等程序实体,这样编译器和相应的开发工具就能够在开发过程当中提供更好的正确性验证和辅助功能(好比IntellSense)。还可让程序员对本身的和其余开发人员的代码表达他的意图,另外ts的类型检测在编译器运行而且没有运行时开销。
好比:
var counter; //未知(any)类型
var counter=0; //number类型(推断出的)
var counter:number; // number类型
var counter:number=0; // number类型
二、变量、基本类型和运算符
这部分简要说明,对ts的基本类型包括boolean、number、string、array、void和全部用户自定义的enum类型。全部的这些类型都是any类型的子类型。来看几种特殊的类型的用法:
第一种:
var list:number[]=[1,2,3];
第二种是使用范型数组类型Array:
var list:Array<number>=[1,2,3];
enum Color{Red,Green,Blue};
var c:Color=Color.Red;
function warnUser:void{
alert("This is my warning message!");
}
var TestStr; //变量声明但未初始化
alert(TestStr); //显示undefined
alert(typeof TestStr); //显示undefined
var TestStr=null; //变量声明,而且被赋值为null
alert(TestStr); //显示null
alert(typeof TestStr); //显示object
然而在TypeScript中,null和undefined不能看成类型来使用:
var TestStr:null; //错误,类型错误
var TestStr:undefined; //错误,找不到undefined
在TypeScript中,当声明一个变量时,可使用var 、let和const关键字:
var myNum:number=-1;
let isValid:Boolean=true;
const appid:string="0FDFD-8989-4CC3-9080-CSDJJFID7HJFD9";
var 声明的变量保存在最近的函数做用域中,若是不存在任何函数中则在全局做用域中。
let声明的变量保存在最近的比函数做用域小的块做用域中,若是不存在则在全局做用域中。
const关键字会建立一个保存在建立位置做用域中的常量,能够是全局做用域也能够是块做用域,这代表const是块做用的,关于做用域的知识会在后面进一步了解。
TypeScript容许联合声明:
var path:string[]|sring;
path='/temp/log.xml';
path=['/temp/log.xml', '/temp/info.xml'];
path=1;
此时path=1;会报类型错误,由于在声明时并未对path进行number的合法声明。
能够在运行时使用typeof或者instanceof运算符对类型进行验证。TypeScript语言服务会在if区域寻找这些运算符,而后对应地更改类型:
var x: any = { /* ... */ };
if(typeof x === 'string') {
console.log(x.splice(3, 1)); // 错误,'string'上不存在'splice'方法
}
// x 依然是 any 类型
x.foo(); // 合法
在这段代码中,咱们首先声明了一个any类型的变量x,随后在运行时经过typeof运算符对x进行了类型检查。若是x的类型为string时,咱们就会尝试调用被认为是x的一个成员的splice方法。TypeScript语言服务能够读懂在条件语句中使用typeof的用法。TypeScript会自动推断出x必定是string类型,而后告诉咱们splice方法不存于string类型上。这种特性被称为类型守护。
TypeScript容许使用type关键字声明类型别名:
type PrimitiveArray = Array<string|number|boolean>;
type MyNumber = number;
type NgScope = ng.IScope;
type Callback = () => void;
可是不建议在一个大的项目团队中使用这种别名,可维护性会下降。
环境声明容许在TypeScript 代码中建立一个不会被编译到 JavaScript中的变量。这个特性是用来促进与现有 JavaScript 代码、DOM(文档对象模型),还有BOM(浏览器对象模型)结合而设计的。让咱们看一个例子:
customConsole.log("A log entry!"); // 错误
若是你尝试调用customConsole对象上的log方法,TypeScript会告诉咱们customConsole对象未被声明:
// Cannot find name 'customConsole'
出现这种状况并不使人意外。可是,有时候咱们但愿调用一个未被定义的对象上的方法,好比window对象上的console方法。
console.log("Log Entry!");
var host = window.location.hostname;
当访问 DOM 或 BOM 对象时,咱们没有遇到错误,是由于这些对象已经在一个特殊的 TypeScript 文件(被称为声明文件)中被声明了。可使用declare操做符建立一个环境声明。
在下面这段代码中,咱们会声明一个被customConsole对象实现的接口。而后使用declare操做符在做用域中增长一个customConsole对象:
interface ICustomConsole {
log(arg : string) : void;
}
declare var customConsole : ICustomConsole;
而后就能够在没有编译错误的状况下使用customConsole:
customConsole.log("A log entry!"); // 成功
TypeScript 默认包含一个名为lib.d.ts的文件,它提供了像 DOM 这种 JavaScript 内置库的接口声明。
使用.d.ts结尾的声明文件,是用来提升 TypeScript 对第三方库和像 Node.js 或浏览器这种运行时环境的兼容性的。
运算符包括:算术运算符、比较运算符、逻辑运算符、位运算符、以及赋值操做符。
这些运算符在这里再也不赘述,若是有开发的基础的话,这些应该都会清楚。
三、流程控制语句
包含选择语句、循环语句和分支语句
if 、if else 、?、switch case 、while 、do while 、for in(相似freach)、for循环,这些语句是咱们再熟悉不过的东东了,也再也不赘述了吧。
四、函数
关于函数,就像JavaScript同样,TypeScript能够经过具名或匿名方式建立,根据具体状况,选择合适的方式声明便可。如:
function greet(name?:string):string{
return "Hi"+name;
}//这是一个带有返回值的具名函数;
//匿名函数
var greet=function(name?:string):string{
return "Hi"+name;
}
若是不想使用函数的语法,还能够有另外一种选择,使用箭头(=>)操做符并不适用function关键字,如:
var greet=(name?:string):string=>{
return "Hi"+name;
}
在这个例子中,咱们还能够给greet变量添加上匹配匿名函数的类型:
var greet=(name?:string)=>string=function(name:string):string{
return "Hi"+name;
}
*注意:当处于类的内部时,若是使用箭头函数(=>)语法将会改变this操做符的工做机制,会在后面的学习中详细讨论。
已经学习了如何将一个变量强制描述为指定形式的函数。这在咱们使用回调函数时是十分有用的。
function sume(a:number,b:number,callback(result:number)=>void){
callback(a+b);
}
五、类
在ES6中添加了基于类的面向对象编程语法,因为TypeScript是基于ES6的,因此咱们能够开始使用基于类的面向对象的语法了。TypeScript的编译器会负责将TypeScript代码编译为兼容主流浏览器和平台的JavaScript代码。
class Person {
fullname: string;
constructor(firstname: string, lastname: string) {
this.fullname = firstname + " " + lastname;
}
hello(name?: string) {
if (name) {
return "Hi! " + name + "! My Name is " + this.fullname;
} else {
return "Hi! My Name is" + this.fullname;
}
}
}
var person = new Person("Allen", "Choi");
var msg = person.hello("Allen");
alert(msg);// "Hi !Allen! My Name is Allen Choi";
var msgnull = person.hello();
alert(msgnull);//"Hi! My Name is Allen Choi"
在上面的例子中,咱们定义了一个Person类,有三个成员:一个fullname属性,一个构造函数constructor和一个greet方法。当在TypeScript中声明类时,全部的属性和方法都是公共的。
当在对象内部访问对象成员时,咱们都加上了this操做符,这代表这是一个成员访问操做,咱们使用new操做符构造了一个Person实例,这会调用类的构造函数,按照定义对实例进行初始化。
为了兼容ES3和ES5,TypeScript中的类会编译为JavaScript中函数
var Person = /** @class */ (function () {
function Person(firstname, lastname) {
this.fullname = firstname + " " + lastname;
}
Person.prototype.hello = function (name) {
if (name) {
return "Hi! " + name + "! My Name is " + this.fullname;
}
else {
return "Hi! My Name is" + this.fullname;
}
};
return Person;
}());
var person = new Person("Allen", "Choi");
var msg = person.hello("Allen");
alert(msg);
var msgnull = person.hello();
alert(msgnull);
六、接口
在TypeScript中,可使用接口来确保类拥有指定的结构。
interface LoggerInterface {
log(arg: any): void;
}
class Logger implements LoggerInterface {
log(arg) {
if (typeof console.log === "function") {
console.log(arg);
} else {
alert(arg);
}
}
}
在这个例子中,咱们定义了一个LoggerInterface接口,和实现了一个Logger的类,Typescript也容许使用接口来约束对象,这样能够帮助咱们避免不少小错误。例以下面的例子中:
interface UserInterface {
name: string;
password: string;
}
var user: UserInterface = {
name:"",
pasword:"" //password 遗漏错误属性
}
七、命名空间
命名空间,又称内部模块,被用于组织一些具备某些内在联系的特性和对象。命名空间可以使代码结构更清晰,可使用namespace和export关键字,在TypeScript中声明命名空间。
namespace Geometry {
interface VertorInterface {
/*...*/
}
export interface Vertor2dInterface {
/*...*/
}
export interface Vertor3dInterface {
/*...*/
}
export class Vertor2d implements VertorInterface, Vertor2dInterface {
/*...*/
}
export class Vertor3d implements VertorInterface, Vertor3dInterface {
/*...*/
}
}
var vector2dInstance: Geometry.Vertor2dInterface = new Geometry.Vertor2d();
var vector3dInstance: Geometry.Vertor3dInterface = new Geometry.Vertor3d();
在上面例子中,咱们声明了一个包含了Vector2d、Vector3d类和VectorInterface、Vector2dInterface、Vector3dInterface接口的命名空间。
*注意:命名空间内的VectorInterface并无export关键字,因此在命名空间外部,咱们访问不到它。
八、综合运用
下面是一个使用了模块、类、函数和类型注解的案例:
module Geometry{
export interface Vector2dInterface{
toArray(callback:(x:number[])=>void):void;
length():number;
normalize();
}
export class Vector2d implements Vector2dInterface{
private _x:number;
private _y:number;
constructor(x:number,y:number){
this._x=x;
this._y=y;
}
toArray(callback:(x:number[])=>void):void{
callback([this._x,this._y]);
}
length():number{
return Math.sqrt(this._x*this._x+this._y*this._y);
}
normalize(){
var len=1/this.length();
this._x*=len;
this._y*=len;
}
}
}
var vector:Geometry.Vector2dInterface=new Geometry.Vector2d(2,3);
vector.normalize();
vector.toArray(function(vectorasArray:number[]){
alert('x:'+vectorasArray[0]+'y:'+vectorasArray[1]);
})
4、小结
这一部分的内容主要是介绍了一些关于TypeScript的基础知识,相信有开发经验的人对这些并不感冒,无论你是用了两分钟看完了,仍是用了20分钟看完了,但愿你能有一点点的收获,内容有书本上的内容,也有网上摘的,若有不对的地方,请多包涵指正。从头看到尾,或许你愈来愈感受它的语法以及一些特性,像极了C#,对于.Net 开发人员来讲应该是再熟悉不过了。后面的内容会持续更新,也但愿本身能坚持下来吧。