【譯】30 分鐘入門 Typescript

原文地址: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 的好處

https://user-gold-cdn.xitu.io/2019/1/25/16882f003afbb612?w=785&h=240&f=png&s=7839
Javascript 已經很好了,我真的須要學習 Typescript 麼?嚴格意義上講,你不須要經過學習 Typescript 去變成一個好的程序員,大部分人沒有使用 Typescript 依然很優秀。固然,使用 Typescript 編程也有一些顯而易見的好處:

  • 由於 Typescript 類型是固定的,用 Typescript 寫的代碼更加容易把控,也更易於調試。
  • 得益於模塊,命名空間和更好的面向對象編程的支持,使得 Typescript 更容易去構建大型和複雜的 apps。
  • 由於 Typescript 有編譯成 Javascript 的過程,使其能夠在項目上線運行和發生錯誤以前能夠捕獲到不一樣類型的錯誤。
  • Angular2 是用 Typescript 寫的,它也推薦開發人員使用 Typescript 去開發項目

最後也很主要的一點,對於大部分人去學 Typescript。 Angular 2 是如今一個很火的編程語言,儘管開發者能夠繼續使用 Javascript 去開發,可是不少教程和例子都是用 Typescript 寫的。隨着 Angular 2 社區的擴展,天然愈來愈多的人會選擇 Typescript. (譯者注:這篇教程寫自2016年,如今react,vue,babel都支持了 Typescript。這篇文章中的 Typescript 的基礎概念對如今仍是適用的)git

https://user-gold-cdn.xitu.io/2019/1/25/16882f003ae58ff3?w=1087&h=405&f=png&s=17276
(近期 Typescript 普及度增長,數據來自谷歌趨勢)

Typescript的安裝

https://user-gold-cdn.xitu.io/2019/1/25/16882f003b536415?w=785&h=240&f=png&s=7766
最簡單安裝 Typescript 的方法是經過 npm 工具,使用如下的命令咱們能夠全局安裝 Typescript,能夠在咱們的項目中使用 Typescript 轉換器:

npm install -g typescript
複製代碼

在命令提示行中輸入 tsc -v 能夠檢查 Typescript 是否被安裝:程序員

tsc -v
Version 1.8.10
複製代碼

支持 Typescript 的編輯器

https://user-gold-cdn.xitu.io/2019/1/25/16882f003b80163a?w=785&h=240&f=png&s=8463

Typescript 是由微軟支持和維護的一個開源項目,因此微軟的Visual Studio原生支持 Typescript。現在,有不少編輯器和IDE均可以原生的或者經過插件來支持 Typescript 的語法提示,自動補充建議,錯誤提醒甚至編譯 Typescript。github

Typescript的編譯

https://user-gold-cdn.xitu.io/2019/1/25/16882f003b9fb43e?w=785&h=240&f=png&s=8475

Typescript通常會寫在.ts(或者.tsx對於jsx來講)文件中,.ts文件不能直接用在瀏覽器中,須要先被轉義成.js文件。Typescript能夠經過如下幾種方式編譯:

  • 經過前文關注過的,命令行工具 tsc
  • 直接在Visual Studio中或者其它IDE中
  • 使用一些前端打包工具例如 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的信息在這個文檔中。

靜態類型

https://user-gold-cdn.xitu.io/2019/1/25/16882f003c68615f?w=785&h=240&f=png&s=9518

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'.
複製代碼

如下是一些最經常使用的數據類型:

  • Number - 全部的數字類型均可以被聲明爲number 類型,它們不會被區分爲int,float或者其它
  • String - 字符串類型,和Javascript字符串類型同樣,能夠被單引號和雙引號包括
  • Boolean - true或者false,若是使用0或1將會報錯
  • Any - 這種變量它能夠被賦值爲各類類型,不管是string,number,或者其它各類類型。
  • Arrays - 有兩種可能的語法:my_arr:number[]; 或者 my_arr: Array
  • Void - 運用在不返回任何值的函數

官方文檔羅列了全部Typescript包含的數據類型

接口

https://user-gold-cdn.xitu.io/2019/1/25/16882f00b25683e0?w=785&h=240&f=png&s=7928

接口被用來檢查一個對象(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的官方文檔

類型和麪向對象編程

https://user-gold-cdn.xitu.io/2019/1/25/16882f00a890f488?w=785&h=240&f=png&s=9637
當構建一個大型的apps的時候,大多數開發者喜歡面向對象編程,尤爲是在java,c#這樣的編程語言裏。Typescript提供了類的系統,它很像Java,c#這樣的語言。包含繼承,抽象類,接口實現,setters/getters和其它。

咱們一樣也關注到最新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類的內容,請閱讀官方文檔

泛型

https://user-gold-cdn.xitu.io/2019/1/25/16882f00b4f8e013?w=785&h=240&f=png&s=7941

泛型是一個模板,它容許函數接受不一樣類型的入參。相較於使用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文檔中包含了兩個高級的例子,包含了泛型類,以及與接口結合使用的方法。若是想閱讀更多,請點擊這裏

模塊

https://user-gold-cdn.xitu.io/2019/1/25/16882f00b66d14f8?w=785&h=240&f=png&s=8391

另外一個關於大型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模塊的內容能夠點擊這裏

聲明文件

https://user-gold-cdn.xitu.io/2019/1/25/16882f05a47f2e54?w=785&h=240&f=png&s=9004
當咱們想使用以前Javascript中常用的庫,咱們須要去使用聲明文件去使得這些庫適用於ts。一個聲明文件的擴展名爲.d.ts,包含了關於庫的信息和API。

ts聲明文件常常是手寫的,可是一些庫也有其它人已經寫好的.d.ts文件。DefinitelyTyped是最大的公共資源倉庫,包含了不少的文件可引用。另外一個著名的用node模塊管理Typescript定義的叫Typings.

更多關於聲明文件的內容能夠看這裏

更多內容

剛開始,閱讀官方文檔的內容可能有點多,可是帶來的收益是巨大的。咱們的教程只是作一個入門的介紹,咱們不可能覆蓋全部文檔的內容。下面是咱們沒有包含到的內容:

最後

但願這篇入門教程能給你帶來幫助。 若是你有任何想法或者想使用Typescript在你的項目裏,能夠在下面留言。

相關文章
相關標籤/搜索