先來講一講TypeScript出現的背景
前端javascript的編程思想與后端java面向對象的編程思想有很大的不同,微軟公司借鑒了coffeescript語言,繼承了很多C#和java的編程思想,推出了TypeScript。期間隨着js的升級換代出了ES6,微軟的TypeScript不僅吸收了ES6的新特性,還可以編譯成ES6的樣子,因此在TypeScript里直接寫ES6的js是基本沒什么問題的。相對於javascript的寬松自由,它添加了更多的約束和規則,是以后javascript發展的主要趨勢。
TypeScript和ES6,ES5的關系如下:
那么TypeScript具體有哪些優點呢
- 編譯
javascript是一種解釋型語言,因此需要通過運行來測試它是否有效。
TypeScript提供錯誤檢查功能,它會編譯成javascript代碼並生成編譯錯誤,有助於在運行腳本之前捕獲所有類型的錯誤,並中斷它們的執行。 - 強大的靜態類型(可以聲明變量的類型)
javascript不是強類型語言。
TypeScript通過自帶的TypeScript語言服務(TLS),一個可選的靜態類型和類型推理系統。 - 由於模塊,命名空間和強大的面向對象編程支持,使構建大型復雜應用程序的代碼庫更加容易。
- angular2框架使用的就是TypeScript
如何安裝、編譯TypeScript
1. 安裝:
npm install -g typescript
查看TypeScript版本:
tsc -v
現在很多文本編輯器和IDE都本身支持或通過插件支持TypeScript語法、智能提示、糾錯。
2. 編譯:
TypeScript是寫在.ts文件里的,不能直接在瀏覽器上運行,需要編譯成js文件后運行。一般有以下幾種方式編譯:
(1) 通過命令行工具tsc
如tsc main.ts,也可以列出所有的文件或者使用通配符來一次編譯多個文件,如:
//構建main.ts和worker.ts tsc main.ts worker.ts //構建所有ts文件 tsc *.ts
(2) 添加配置文件tsconfig.json,包含多種構建設置,從而實現自動化進程
{ "compilerOptions": { "target": "es5", //指定生成代碼的兼容版本 "importHelpers": true, "lib": [ "es2016", "dom" ], "moduleResolution": "node", //指定模塊的解析策略,Node或者是classic,默認是classic。 "emitDecoratorMetadata": true, //設置為true,則使用元數據特性 "experimentalDecorators": true, //設置為true,則支持ES7的裝飾器特性 "strictNullChecks": true, "alwaysStrict": true, "noImplicitAny": false, //當表達式和申明類型為any時,是否需要發出警告,設置true,則不警告 "noUnusedLocals": true, "baseUrl": "", "paths": { "@schenker/foundation": ["portal/nges-portal-web/src/main/resources/webapp/js/portal-framework"], "@schenker/eservice-portal-entry": ["eservices/portal-entry/eservices-portal-entry-web/src/main/resources/webapp/js/portal-entry/eservice.ts"], "@schenker/eservice-booking": ["eservices/booking/eservices-booking-web/src/main/resources/webapp/js/booking/eservice.ts"], "@schenker/eservice-sla-reporting": ["eservices/sla-reporting/eservices-sla-reporting-web/src/main/resources/webapp/js/sla-reporting/eservice.ts"] }, //typeRoots和types選項指定了node_modules/@types下的jasmine,angular等包括在內,其余的type不適用 "typeRoots": ["node_modules/@types"], "types": [ "jasmine", "angular", "node", "webpack", "webpack-env", "spin.js", "jquery", "moment", "angular-mocks" ] }, //用於排除不需要編譯的ts文件。該屬性和files屬性沖突。兩者只能設置其一。 "exclude": [ "node_modules/*" ], "angularCompilerOptions": { "preserveWhitespaces": false } }
更多配置選項可以查看TypeScript官方文檔: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
具體配置解析也可以看:https://github.com/hstarorg/HstarDoc/blob/master/%E5%89%8D%E7%AB%AF%E7%9B%B8%E5%85%B3/TypeScript%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6tsconfig%E7%AE%80%E6%9E%90.md
(3) 使用自動化構建工具,如gulp或webpack
TypeScript基本語法
1.基本類型
boolean
let isDone: boolean = false;
number: 所有數字都是數值類型的,無論是整數、浮點型或者其他數值類型都相同。
let height: number = 6;
string
let name1: string = 'tom';
array
let list:number[] = [1, 2, 3];
let list1:Array<number> = [1, 2, 3];
enum
enum Color {Red, Green, Blue} let c: Color = Color.Green; console.log(c); // 獲取值,相當於 console.log(Color["Green"]); enum Color1 {Red = 1, Green = 2, Blue = 4} let c1: Color1 = Color1.Green; console.log(c1); // 獲取值,2
any: any可以是任意對象,會根據需要改變數據類型
let anylist:any[] = [1, true, "free"]; anylist[2] = 100;
void: 不返回值
function warnUser(): void { console.log("This is my warning message"); } warnUser();
2.接口
為什么需要接口呢,可以看以下一段代碼:
function calculateResult({x=0, y=0}:{x:number, y:number}){ //calculate method } function calculateResult2({x=0, y=0, z=0}:{x:number, y:number, z:number}){ //calculate method }
如果有很多個參數需要進行計算的話,那么我們需要不斷復制增加參數,整個代碼會非常臃腫,但是有了接口之后,會非常方便。如:
function calculateResult({x=0, y=0}:pointer2d){ //calculate method } function calculateResult2({x=0, y=0, z=0}:pointer3d){ //calculate method } interface pointer2d { x: number; y: number; } interface pointer3d extends pointer2d { z: number; }
接口的作用就是去描述結構的形態。
接口通常會根據一個對象是否符合某種特定結構來進行類型檢查。通過定義一個接口我們可以命名一個特殊的組合變量,確保它們會一直一起運行。
interface LabelledValue { label: string; } function printLabel(labelledObj: LabelledValue) { console.log(labelledObj.label); } var myObj = {label: "only label"}; var myObj1 = {size: 10, label: "Size 10 Object"}; // # 接口是鴨子類型, 只要是有label的對象都可以傳進去 printLabel(myObj); printLabel(myObj1);
接口還有其他一些玩法,如:
(1)可選屬性
interface SquareConfig { color?: string; // 用?來表示可選屬性 width?: number; } function createSquare(config: SquareConfig): {color: string; area: number} { var newSquare = {color: "white", area: 100}; if (config.color) { newSquare.color = config.color; } if (config.width) { newSquare.area = config.width * config.width; } return newSquare; } var mySquare = createSquare({color: "black"}); var mySquare1 = createSquare({width: 20}); console.log(mySquare); console.log(mySquare1);
(2)函數類型
interface SearchFunc { (source: string, subString: string): boolean; // 表示一個接受2個string參數, 返回bool的函數 } var mySearch: SearchFunc; mySearch = function(source: string, subString: string): boolean { var result = source.search(subString); if (result == -1) { return false; } else { return true; } }; var result: boolean = mySearch("test", "te"); console.log(result);
(3)數組類型
interface StringArray { [index: number]: string; // 表示string數組 } var myArray: StringArray; myArray = ["Bob", "Fred"]; console.log(myArray["0"]); console.log(myArray["1"]);
(4)類類型
interface ClockStatic { new (hour: number, minute: number); } // # 這里會報錯. 因為只有實例部分才檢查, 而構造函數是靜態部分 //class Clock implements ClockStatic { // currentTime: Date; // constructor(h: number, m: number) { } //} class Clock { currentTime: Date; constructor(h: number, m: number) { } } // # 這里需要注意 // # 我們直接使用class,這樣就會檢查簽名 var cs: ClockStatic = Clock; var newClock: ClockStatic = new cs(7, 30); console.log(newClock);
(5)繼承接口
interface Shape { color: string; } interface PenStroke { penWidth: number; } interface Square extends Shape, PenStroke { // 使用extends繼承接口 sideLength: number; } var square = <Square>{}; square.color = "blue"; square.sideLength = 10; square.penWidth = 5.0;
未待完續.........