TypeScript是一种由微软开发的自由和开源的编程语言。它是JavaScript的一个超集,并且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。 TypeScript扩展了JavaScript的句法,因此任何现有的JavaScript程序能够不加改变的在TypeScript下工做。TypeScript是为大型应用之开发而设计,而编译时它产生 JavaScript 以确保兼容性。 TypeScript 支持为已存在的 JavaScript 库添加类型信息的头文件,扩展了它对于流行的库如 jQuery,MongoDB,Node.js 和 D3.js 的支持。java
TypeScript数据类型包括:Boolean, Number, String, Array, Enum, Any,Void七种es6
let isDone: boolean = false;
跟JavaScript同样,TypeScript全部的数值类型采用浮点型计数,其类型为‘number’。typescript
let height: number = 6.32322;
TypeScript和JavaScript同样也是用双引号(“)或者单引号包裹文本数据。编程
let name: string = "bob";
在TypeScript中如JavaScript同样容许咱们操结合操做。数组类型可使用下边两种方式之一。第一种方式,你能够在数据类型以后带上’[ ]‘:json
let list:number[] = [1, 2, 3];
第二种方式,也能够采用泛型的数组类型:c#
let list:Array<number> = [1, 2, 3];
TypeScript为JavaScript新增了枚举这种标准的集合数据类型。和在c#中同样,枚举是为一组数值类型一组更友好的名称:数组
// 定义枚举 enum Color {Red, Green, Blue}; // 引用枚举 let c: Color = Color.Green;
或是手动设置所有的枚举成员:app
enum Color {Red = 1, Green = 2, Blue = 4}; let c: Color = Color.Green;
运用枚举类型能够很容易从一个数值类型获取对应枚举名称。例如咱们有一个数值类型2,但不确认将匹配哪个枚举成员,那么咱们能够以下使用:编程语言
enum Color {Red = 1, Green, Blue}; let colorName: string = Color[2]; console.log(colorName);
有时咱们须要描述一些咱们不知道的出现于应用中的动态数据类型,这可能来自第三方用户或者lib。在这里咱们但愿该数据不要加入TypeScript的类型检查,而且能跳过编译检查。为此咱们能够采用‘any’类型标注:ide
let notSure: any = 4; notSure = "maybe a string instead"; notSure = false;
‘any’类型是一种强大的兼容存在的JavaScript库的类型系统。他容许跳过TypeScript的编译时类型的检查。 ‘any’类型对应于咱们只知道部分数据类型,可是不是全部的数据类型的类型系统。例如一个混合了多种类型的集合数组。
let list:any[] = [1, true, "free"]; list[1] = 100;
和‘any’相对的数据类型则是’Void‘,它表明没有任何数据类型。一般用于表示一个方法没有任何返回值:
warnUser(): void { console.log("This is my warning message"); }
与JavaScript彻底相同,须要注意的是临时变量须要加上数据类型
let someValPoint: Point = new Point();
interface Point { x: number; y: number; }
interface ThreeDPoint extends Point { z: number; }
const pointObjectFirst = { x: 2, y: 1 }; const pointObjectSecond = { x: 3, y: 32 }; const threeDPoint = { x: 20, y: 11, z: 50 };
// obj数据类型调用 addPoints(pointObjectFirst, pointObjectSecond); // 接口类型数据调用,假设interfaceObjFirst,interfaceObjSecond,是两个已实现接口Point的类,那么实例化以后调用方式为: addPoints(interfaceObjFirst, interfaceObjSecond); /** * 测试方法 * @param pointOne * @param pointTwo * @returns {{x: any, y: any}} */ addPoints( pointOne: any, pointTwo: any) { return { x: p1.x + p2.x, y: p1.y + p2.y }; }
从上面例子来看,若是经过{}定义的数据,缺乏某个属性,好比x,ide不会报错,但若是使用接口,则没法往下编译。另外须要补充的是:接口的基本用途,规定子类的行为,接口在实际开发过程当中最大好处在于咱们能够按照设计,先把接口写好,而后你们干活的时候,能够用写好的接口去实现他们的具体功能,避免用{}方式定义有可能某些属性没有而报错,若是用接口定义,排错功能在写代码时ide已帮咱们查找到了,因此这样能提升一些工做效率。
// 定义类 class Point { /*定义静态属性*/ static origin = new Point(0, 0); /*定义静态方法*/ static getRule(p1: Point, p2: Point) { return p1.add(p2); } /*构造体*/ constructor(private xValue: number, private yValue: number) { } /*定义set*/ get x() { return this.xValue; } /*定义set*/ set x(value: number) { this.xValue = value; } /*定义方法(默认公有,可不写public关键字)*/ add(point: Point) { return new Point(point.x + this.x, point.y + this.y); } /*定义方法(显式声明公有,写public关键字)*/ public addSides(point: Point) { return new Point(point.x + this.x, point.y + this.y); } /*定义方法(私有,写private关键字)*/ private getArea(point: Point) { return new Point(point.x + this.x, point.y + this.y); } } // 类的实例化及方法调用 let pointAdder:Point = new Point(2, 1); let pointAdded:Point = new Point(23,32); let addValue:number = pointAdded.add(pointAdder); let pointStatic = Point.getRule(p1, p2);
注意:与es5不一样,TypeScript舍去了定义方法时使用的function关键字,这样更简洁。同时支持private私有成员,更方便信息隐藏。
继承能够简化对类定义的描述,提升代码重用,是多态的基础。如下以图型Shape类做演示
/*多边形基类定义*/ class Polygon { height: number; /*构造方法*/ constructor(height: number) { this.height = height; } /*定义公有方法*/ public computeArea(): number { return 0; } /*定义私有方法*/ private getSides(): number { return 0; } } /*三角形继承自多边形基类,拥用基类public属性和方法*/ class Triangle extends Polygon { /*自定义属性*/ base: number; /*构造体,初始化自已还经过super调用了父类构造体*/ constructor(height: number, base: number) { super(height); this.base = base; } /*重写父类公用方法,即俗称一样方法名子类有自已的实现*/ public computeArea() { return .5 * this.base * this.height; } } /*长方形继承自多边形基类,拥用基类public属性和方法,也定义了自身新的属性*/ class Rectangle extends Polygon { /*新的属性*/ width: number; /*构造体,初始化自已还经过super调用了父类构造体*/ constructor(height: number, width: number) { super(height); this.width = width; } /*重写父类公有方法*/ public computeArea() { return this.height * this.width; } } /*正方形继承自长方形类*/ class Square extends Rectangle { /*构造体,初始化自已还经过super调用了父类(Rectangle)构造体*/ constructor(length: number) { super(length, length); } /*重写父类公有方法,加入了自身不一样于父类的实现*/ public computeArea() { return this.width * this.width; } }
/*定义接口*/ interface Shape { /*定义接口模板方法,实现此接口的类必须实现此接口的全部具体方法,不然没法编译*/ computeArea: () => number; } /*实现Shape接口,支持多接口实现*/ class Polygon implements Shape { height: number; /*实现接口方法,由每一个类具体实现,内容能够不一样,但方法体必须相同*/ computeArea() { return 0; } } /*实现Shape接口*/ class Elipse implements Shape { a: number; b: number; constructor(a: number, b: number) { this.a = a; this.b = b; } /*实现接口方法,由每一个类具体实现,内容能够不一样,但方法体必须相同*/ computeArea() { return Math.PI * this.a * this.b; } }
使用接口编程,类之间通讯简单易懂,扩展性好,能提升复用、扩展性,耦合松散,适合于大中型项目模块代码质量控制。
class OverLoad { /*定义方法foo,使用number型的2个参数,返回number类型结果*/ foo(a: number, b: number): number; /*定义方法foo,使用string型的2个参数,返回string类型结果(发生重载行为)*/ foo(a: string, b: string): string; /*定义方法foo,使用any型的2个参数,返回any类型结果(发生重载行为)*/ foo(a:any, b:any): any { if (typeof a == "string" && typeof b == "string") { return a + " " + b; } return a + b; } } let ol:OverLoad = new OverLoad(); ol.foo(1, 2); // 直接调用,调用了number类型参数的方法 ol.foo('xxd','xxd'); // 重截调用,调用了string类型参数的方法
请注意:typescript目前只支持等量参数重载,不支持,相同方法名,不一样参数数量和类型的重载。
泛型的本质是参数化类型,也就是说所操做的数据类型被指定为一个参数。这种参数类型能够用在类、接口和方法的建立中,分别称为泛型类、泛型接口、泛型方法。
能够把类型参数看做是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符同样。
泛型典型应用即在集合类数据类型中。例如,要定义个相似Map的类容许您向一个 Map 添加任意类的对象,即便最多见的状况是在给定映射(map)中保存某个特定类型(好比 String)的对象。
/*定义泛型通常使用T*/ foo<T>(a: T) { return a; } // 泛型运用 let bar:any = foo<string>("hello world"); let barNumber:any = foo<number>(10); let barElement:any = foo<HTMLElement>(document.createElement("div")); let bazArray:any = new Array<string>(); let json = '{"firstName":"John","lastName":"Doe"}'; interface Person { firstName: string; lastName: string; } interface Person2 { firstName: string; lastName: string; } let myJSON = { parse: function <T>(data: string) : T { return JSON.parse(data); } }; let obj:any = myJSON.parse<Person>(json); class Foo<T extends Person> { foo: T; bar(data: T) { } baz(): T { return this.foo; } } let obj2:any = new Foo<Person2>();
模块导入:import 模块导出:export
/** * 导出shape * file: shapes.ts */ export interface Shape { computeArea: () => number; } // 导入shapes接口 import shapes from "shapes"; /** * 导出ellipse类,并实现自导入的shapes接口 * file: ellipses.ts */ export class Ellipse implements shapes.Shape { a: number; b: number; constructor(a: number, b: number) { this.a = a; this.b = b; } computeArea() { return Math.PI * this.a * this.b; } } /** * 导出继承类 * file: ellipses.ts */ export class Circle extends Ellipse { radius: number; constructor(radius: number) { super(radius, radius); this.radius = radius; } } // file: app.ts // 导入类 import ellipses from "ellipses"; // 实例化使用,由导入句柄名+引用句柄所引用方法 let circle = new ellipses.Circle(4);
使用module、export、reference关键字组合使用
/** * 统必定义模块使名空间Shapes * file: shapes.ts */ module Shapes { export interface Shape { computeArea: () => number; } } /** * 引用接口类,一样位于Shapes空间中 * file: polygons.ts */ /// <reference path="shapes.ts" /> module Shapes { export class Polygon implements Shape { height: number; constructor(height: number) { this.height = height; } computeArea() { return 0; } } export class Triangle extends Polygon { base: number; constructor(height: number, base: number) { super(height); this.base = base; } computeArea() { return .5 * this.base * this.height; } } } /** * 引用,位于Shapes命名空间中内容 */ /// <reference path="polygons.ts" /> let triangle = new Shapes.Triangle(4, 4);
建议:在模块内建立类,组织类时遵循类的单一性功能,来实现对类复杂度解耦,即一个文件对应一个类,且只包含一种功能。