為什麼要用typescript
這裡列舉了兩個主要的目的
- typescript為js提供了可選的型別系統(type system)
- typescript為當前的js引擎提供了未來JS版本才能使用的特性
typescript的型別系統
你獲取想知道為什麼要給javascript新增型別系統呢?
型別系統已經被證明是一種可以增強程式碼質量和可讀性的能力,大型團隊(例如谷歌,微軟,facebook)都在印證著這個結論,更具體點說:
- 當要進行程式碼重構時,型別系統能給予更高的靈活度,因為在編譯時進行異常捕獲要好於在執行時
- 型別系統是最好的文件格式之一,函式簽名(function signature)是一個定理,而函式體則是相應的證明(proof)
typescript會盡量保持一個低門檻,來保證開發者可以低成本的學習編寫ts程式碼
你的js程式碼就是ts程式碼
typescript為js提供了編譯時的型別檢查,最棒的是型別完全是可選的,你的js程式碼(.js檔案)可以重新命名成(.ts)檔案,typescript同樣會返回和原有js檔案一樣的輸出。通過可選的型別檢查,typescript就是嚴格的js超集。
型別可以是隱式的
在程式碼開發階段,typescript會盡可能用比較低的成本去推斷儘可能多的型別資訊,例如,在接下來的例子中,typescript將會知道foo是number型別,當在第二行程式碼中又給foo賦值為一個字串型別的值時,就會報出錯誤
var foo = 123;
foo = '456'; // Error: cannot assign `string` to `number`
複製程式碼
這種型別推斷具有良好的動機,如果你也有像上述例子相似的場景,在接下來的程式碼中,並不確定foo到底是number型別還是string型別,這樣的問題在大型的多檔案程式碼庫中經常能碰到,我們稍後會繼續深入瞭解型別推斷的規則。
型別可以是顯式的
根據我們在之前提到的,typescript將會盡能安全的進行型別的推斷,然而,也可以使用註解去明確達到下面兩個目的
- 有助於編譯器進行友好的提示,還有就是對於那些不得不閱讀你程式碼的開發者,文件的填充也是非常重要的
- 強制讓在編譯器上看到的提示就是你希望讓使用者(閱讀你程式碼的開發者)看到的提示,也就是說,你對於程式碼的理解匹配了程式碼的演算法分析(這一步通過編譯器來完成)
typescript是用尾隨式的型別註解
var foo: number = 123;
複製程式碼
下面這個例子編譯器將會丟擲一個error
var foo: number = '123'; // Error: cannot assign a `string` to a `number`
複製程式碼
我們會在後續章節討論註解語法的細節
typescript是結構化的
在typescript中,我們想讓js開發者以更小的學習成本來編寫ts程式碼,所以型別都是結構化的,這意味著,”鴨子型別“是一種類(class)語言優先的結構,考慮下面這個例子,函式iTakePoint2D將會接收任何包含了x和y的物件作為引數
interface Point2D {
x: number;
y: number;
}
interface Point3D {
x: number;
y: number;
z: number;
}
var point2D: Point2D = { x: 0, y: 10 }
var point3D: Point3D = { x: 0, y: 10, z: 20 }
function iTakePoint2D(point: Point2D) { /* do something */ }
iTakePoint2D(point2D); // exact match okay
iTakePoint2D(point3D); // extra information okay
iTakePoint2D({ x: 0 }); // Error: missing information `y`
複製程式碼
型別錯誤不會阻止js程式碼的執行
為了使js程式碼遷移到ts程式碼更為簡單,即使是有編譯錯誤,預設的,typescript也會觸發有效的js程式碼使其正常執行
var foo = 123;
foo = '456'; // Error: cannot assign a `string` to a `number`
複製程式碼
等價於觸發下面這段js程式碼
var foo = 123;
foo = '456';
複製程式碼
所以從js程式碼過渡到ts程式碼可以採用逐漸更新升級的策略,這也是ts不同於其他語言編譯器工作以及遷移到ts的原因
型別可以是調節粒度的
typescript的一個主要的設計目標就是可以在typescript儘可能簡單和安全的使用已經存在的js庫,typescript通過宣告(declaration)來達到這個目的,typescript提供了一個可變的比例針對你想在宣告檔案中放置多少宣告資訊,宣告的越具體,型別檢測和程式碼提示就越詳細,注意,針對大多數流行的js庫已經有寫好的宣告檔案[github.com/borisyankov…](DefinitelyTyped community), 所以針對大多數的目的:
- 宣告檔案已經存在
- 或者至少,已經有大量的經過了review的宣告模版可用了
為了快速定義一個自己的宣告檔案,以jQuery為例,預設的,在你使用一個變數之前,typescript都期望你首先要宣告它
$('.awesome').show(); // Error: cannot find name `$`
複製程式碼
為了快速解決這個問題,你可以告訴typescript,這裡確實有一個叫做$的傢伙
declare var $: any;
$('.awesome').show(); // Okay!
複製程式碼
如果你想基於這個基礎的定義來提供更多的資訊以防止出現編譯error,可以這樣做
declare var $: {
(selector:string): any;
};
$('.awesome').show(); // Okay!
$(123).show(); // Error: selector needs to be a string
複製程式碼
現在就能使用js的新特性
typescript提供了很多新特性針對當前的js引擎,typescript團隊也在積極的新增這些特性,這份特性列表也會隨著時間變得越來越豐富,這裡以一個class為例。
class Point {
constructor(public x: number, public y: number) {
}
add(point: Point) {
return new Point(this.x + point.x, this.y + point.y);
}
}
var p1 = new Point(0, 10);
var p2 = new Point(10, 20);
var p3 = p1.add(p2); // { x: 10, y: 30 }
複製程式碼