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);
建議:在模塊內建立類,組織類時遵循類的單一性功能,來實現對類複雜度解耦,即一個文件對應一個類,且只包含一種功能。