原文地址:learn-typescript-in-30-minutesjavascript
原文做者:Danny Markovhtml
譯者:Jerry前端
譯文首發地址:jerryjiao.life/vue
今天咱們來學習 Typescript,一門被設計用來開發大型和複雜 apps 的語言。相較於鬆散的,弱類型的 Javascript , Typescript 繼承了不少其它高級語言( c# , java )的概念,進而更加的規範。java
這篇入門針對於有必定的 Javascript 基礎而且打算學習 Typescript 的人。咱們覆蓋了不少基礎和關鍵的概念,並輔以不少例子來幫助你理解這門語言。讓咱們開始吧。node
(譯者說明:這篇文章不算新,16年末的文章。可是我瀏覽了其它一些英文的 Typescript 入門的文章,感受仍是這篇文章覆蓋的內容全面一些,更適合初學者。並且一些基礎內容,是變化不大的,因此選擇了這篇文章。翻譯這篇文章的時候,一些2.0新特性的簡述的內容沒有翻譯,由於已是發佈過的了。)react
最後也很主要的一點,對於大部分人去學 Typescript。 Angular 2 是如今一個很火的編程語言,儘管開發者能夠繼續使用 Javascript 去開發,可是不少教程和例子都是用 Typescript 寫的。隨着 Angular 2 社區的擴展,天然愈來愈多的人會選擇 Typescript. (譯者注:這篇教程寫自2016年,如今react,vue,babel都支持了 Typescript。這篇文章中的 Typescript 的基礎概念對如今仍是適用的)git
(近期 Typescript 普及度增長,數據來自谷歌趨勢)npm install -g typescript
複製代碼
在命令提示行中輸入 tsc -v
能夠檢查 Typescript 是否被安裝:程序員
tsc -v
Version 1.8.10
複製代碼
Typescript 是由微軟支持和維護的一個開源項目,因此微軟的Visual Studio原生支持 Typescript。現在,有不少編輯器和IDE均可以原生的或者經過插件來支持 Typescript 的語法提示,自動補充建議,錯誤提醒甚至編譯 Typescript。github
Typescript通常會寫在.ts(或者.tsx對於jsx來講)文件中,.ts文件不能直接用在瀏覽器中,須要先被轉義成.js文件。Typescript能夠經過如下幾種方式編譯:
tsc
gulp
咱們發現第一種方式更加簡單也對初學者更友好,因此在這篇文章中咱們將會使用第一種方式。
下面的命令將會轉換main.ts這個Typescript文件爲main.js.若是main.js存在,它將會被覆蓋。
tsc main.ts
複製代碼
咱們也能夠羅列多個文件或者使用通配符去編譯:
# 將會編譯出分離的Javascript文件: main.js worker.js
tsc main.ts worker.ts
# 編譯全部的在這個目錄下的全部ts文件,不能遞歸執行。
tsc *.ts
複製代碼
咱們也可使用--watch來自動編譯Typescript文件在Typescript文件改變時:
# 初始化一個watcher的進程來保持main.js爲最新
tsc main.ts --watch
複製代碼
更多Typescript的用戶也使用建立 tsconfig.json, 包含不一樣的編譯的配置。配置文件對一個包含不少的.ts文件的項目編譯很便利,由於它定義了自動化的流程。你能夠得到更多包含tsconfig.json的信息在這個文檔中。
Typescript一個很是明顯的特徵就是支持靜態的類型。這就意味着,在聲明變量的時候要同時聲明變量的類型,編譯器會保證變量不會被賦值爲錯誤的類型。一旦變量的類型被聲明,他們將會從你的代碼中作到自動的推測。
這裏是一個例子,任何的變量,函數以及返回值在一開始都要被聲明類型:
var burger: string = 'hamburger', //String
calories:number = 300, // Numberic
tasty: boolean = true; //Boolean
// 天然地,你也能夠 省略變量的聲明
// var burger = 'hamburger'
// 函數通常返回一個string或數字
// 若是函數爲void類型,它將不會返回什麼東西
function speak(food:string, energy:number):void {
console.log("Our " + food + " has " + energy + " calories.");
}
speak(burger, calories);
複製代碼
正由於Typescript將會被轉爲js, 一些沒有語義和類型的字符,將會被移除:
// 一個Typescript轉爲js的例子
var burger = 'hamburger',
calories = 300,
tasty = true;
function speak(food, energy) {
console.log("Our " + food + " has " + energy + " calories.");
}
speak(burger, calories);
複製代碼
固然,若是你的代碼不符合規則,tsc命令行工具將會警告咱們錯誤在哪,好比:
// 當變量被聲明爲boolean,但被賦值爲string的時候
var tasty: boolean = "I haven't tried it yet";
複製代碼
main.ts(1,5): error TS2322: Type 'string' is not assignable to type 'boolean'.
複製代碼
若是咱們寫錯函數的入參類型,tsc也會提示:
function speak(food: string, energy: number): void{
console.log("Our " + food + " has " + energy + " calories.");
}
// 函數入參的類型錯誤
speak("tripple cheesburger", "a ton of");
複製代碼
main.ts(5,30): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
複製代碼
如下是一些最經常使用的數據類型:
官方文檔羅列了全部Typescript包含的數據類型
接口被用來檢查一個對象(object)是否符合固定的結構。經過定義接口,咱們能夠命名一個特殊的變量的組合,確保它們的是固定的。當轉譯爲Javascript的時候,接口將會消失-接口的目標就是在開發過程當中給予幫助。
下面的例子,咱們定義一個簡單的接口對函數的入參進行類型檢查:
// 這裏咱們定義了一個 Food的接口,包含它的屬性和其類型
interface Food {
name: string;
calories:number;
}
// 咱們能夠告訴函數咱們但願的入參,來符合Food這個接口
// 這種方式能夠保證屬性永遠的可用
function speak(food: Food): void {
console.log("Our " + food.name + " has " + food.calories + " calories.");
}
// 咱們定義一個對象,它知足Food接口規定的屬性
// 注意 這個類型將被自動的推測
var ice_cream = {
name: "ice cream",
calories: 200
}
speak(ice_cream);
複製代碼
屬性的順序不重要,咱們要保證屬性名字和類型的正確。若是少了某些屬性,或者寫了錯誤的類型,或者名字不一樣,ts的編譯器都會警告咱們。
interface Food {
name: string;
calories: number;
}
function speak(food: Food): void{
console.log("Our " + food.name + " has " + food.calories + " grams.");
}
// 咱們寫了一個錯誤的屬性名 nmae
var ice_cream = {
nmae: "ice cream",
calories: 200
}
speak(ice_cream);
複製代碼
報錯信息:
main.ts(16,7): error TS2345: Argument of type '{ nmae: string; calories: number; } is not assignable to parameter of type 'Food'. Property 'name' is missing in type '{ nmae: string; calories: number; }'. 複製代碼
這是一個面對初學者的教程,若是你想得到更多關於interface的信息,請訪問ts的官方文檔
咱們一樣也關注到最新Javascript的更新(ECMAScript 2015),Javascript原生對class提供了支持。Typescript和Javascript對類的應用很類似,可是有不一樣的地方。Typescript更嚴格一些。
延續以前food例子的風格,下面是一個簡單的Typescript類的例子:
class Menu {
// 類中的屬性:
// 默認的,它們是public的,也能夠是private 或者 protected
items: Array<string>; // 在菜單中的項目,一個strings類型的數組
pages: number; // 菜單有多少頁面,一個數字
// 構造函數
constructor(item_list: Array<string>, total_pages: number) {
// 這裏的關鍵詞是強制的
this.items = item_list;
this.pages = total_pages;
}
// 方法
list(): void {
console.log("Our menu for today:");
for(var i=0; i<this.items.length; i++) {
console.log(this.items[i]);
}
}
}
// 建立一個新的‘菜單’類實例
var sundayMenu = new Menu(["pancakes","waffles","orange juice"], 1);
// 執行list方法
sundayMenu.list();
複製代碼
熟悉java或c#的程序員對這種語法應該感受很熟悉,下面是繼承的例子:
class HappyMeal extends Menu {
// 父類屬性將會被繼承
// 須要定義一個新的構造函數
constructor(item_list: Array<string>, total_pages: number) {
// 在這個例子中,咱們但願和父類有一樣的構造函數
// 爲了更方便額度複製父類的構造函數,這裏使用了super函數-引用了父類的構造函數
super(item_list, total_pages);
}
// 和屬性同樣,父類函數也會被繼承
// 固然咱們也能夠重寫list()函數覆蓋父類中的方法
list(): void{
console.log("Our special menu for children:");
for(var i=0; i<this.items.length; i++) {
console.log(this.items[i]);
}
}
}
// Create a new instance of the HappyMeal class.
var menu_for_children = new HappyMeal(["candy","drink","toy"], 1);
// This time the log message will begin with the special introduction.
menu_for_children.list();
複製代碼
若是想更深刻的瞭解Typescript類的內容,請閱讀官方文檔
泛型是一個模板,它容許函數接受不一樣類型的入參。相較於使用any這個類型,用泛型建立一個複用的組件會更好,由於泛型保留了進出變量的類型。
下面是一個簡單的例子,這個函數會接收一個參數而且返回包含這個參數的數組。
// 在函數後面的<T>標識符表示了一個函數爲泛型函數
// 當咱們執行函數的時候,每個T的實例將會被替換爲真實提供的類型
// 接收一個入參,類型爲T
// 返回一個數組,類型爲T
function genericFunc<T>(argument: T): T[] {
var arrayOfT: T[] = []; //建立一個T類型的空數組
arrayOfT.push(argument); // 入參添加進這個數組中
return arrayOfT;
}
var arrayFromString = genericFunc<string>("beep");
console.log(arrayFromString[0]); // "beep"
console.log(typeof arrayFromString[0]) // String
var arrayFromNumber = genericFunc(42);
console.log(arrayFromNumber[0]); // 42
console.log(typeof arrayFromNumber[0]) // number
複製代碼
第一次咱們執行函數的時候,咱們不須要手動的傳入的參數的類型(string),由於編譯器能夠識別到傳遞了什麼參數,並自動決定什麼類型最適合它;就像在第二個調用中那樣,雖然這不是必須的,可是仍是推薦每次都指定泛型的類型,由於編譯器可能在複雜的情景下推測出錯誤的類型。
Typescript文檔中包含了兩個高級的例子,包含了泛型類,以及與接口結合使用的方法。若是想閱讀更多,請點擊這裏。
另外一個關於大型apps的概念是模塊化。若是你的代碼能夠劃分爲許多小的,可重複使用的模塊,將會使你的項目更加條理和易於理解的。比一個有10000行的文件好不少。
Typescript引入了一種語法去輸出和引入模塊,可是沒法掌控文件間的實際鏈接。爲了能使Typescript文件使用第三方的庫,例如用在瀏覽器apps的require.js和Node.js的CommmonJs.讓咱們看一個簡單的例子--Typescript模塊和require.js:
咱們有兩個文件,一個輸出函數,另外一個引入它而且執行它:
expoter.ts
var sayHi = function():void {
console.log("Hello!");
}
export = sayHi;
複製代碼
importer.ts
import sayHi = require('./exporter');
sayHi();
複製代碼
如今咱們須要下載require.js並用 <script>
標籤引入到文件中 -
這裏會告訴你怎麼作。最後一個是轉換這兩個.ts文件。在轉換的時候輸入另外一個參數,告訴編譯器咱們想使用AMD的方式引用,而不是 CommonJS 的方式
tsc --module amd *.ts
複製代碼
若是你想了解更多Typescript模塊的內容能夠點擊這裏。
ts聲明文件常常是手寫的,可是一些庫也有其它人已經寫好的.d.ts文件。DefinitelyTyped是最大的公共資源倉庫,包含了不少的文件可引用。另外一個著名的用node模塊管理Typescript定義的叫Typings.
更多關於聲明文件的內容能夠看這裏。
剛開始,閱讀官方文檔的內容可能有點多,可是帶來的收益是巨大的。咱們的教程只是作一個入門的介紹,咱們不可能覆蓋全部文檔的內容。下面是咱們沒有包含到的內容:
但願這篇入門教程能給你帶來幫助。 若是你有任何想法或者想使用Typescript在你的項目裏,能夠在下面留言。