博客 / 詳情

返回

Y 分鐘速成 TypeScript

源代碼下載: learntypescript-cn.ts

TypeScript 是一門為開發大型 JavaScript 應用而設計的語言。TypeScript 在 JavaScript 的基礎上增加了類、模塊、接口、泛型和靜態類型(可選)等常見的概念。它是 JavaScript 的超集:所有 JavaScript 代碼都是有效的 TypeScript 代碼,因此任何 JavaScript 項目都可以無縫引入 TypeScript,TypeScript 編譯器最終會把 TypeScript 代碼編譯成 JavaScript 代碼。

本文只關注 TypeScript 額外增加的區別於 JavaScript 的語法。

如需測試 TypeScript 編譯器,你可以到 Playground 編寫代碼,它會自動將你編寫的 TypeScript 代碼編譯成 JavaScript 代碼後,在右側即時展示出來。

// TypeScript 有三種基本類型,布爾類型、數值類型、字符串類型
let isDone: boolean = false;
let lines: number = 42;
let name: string = 'Anders';

// 如果不知道是什麼類型,可以使用 "any" (任意)類型
let notSure: any = 4;
notSure = '可以重新賦值,轉換為字符串類型';
notSure = false; // 亦可,重新定義為布爾類型

// 使用 const 關鍵字將一個字面量修飾為常量
const numLivesForCat = 9;
numLivesForCat = 1; // 常量不能重新被賦值,所以這裏會報錯

// TypeScript 中的 collection 有兩種表示形式, 一種是有類型的數組,另一種是泛型數組
let list: number[] = [1, 2, 3];
// 或者,使用泛型數組
let list: Array<number> = [1, 2, 3];

// 枚舉
enum Color {Red, Green, Blue}
let c: Color = Color.Green;

// 最後是 "void",它用於表明函數沒有任何返回值的特殊情況
function bigHorribleAlert(): void {
 alert('我是個煩人的彈出框!');
}

// 函數是"一等公民"(first class citizens), 支持使用 lambda 胖箭頭表達式和類型推斷

// 以下 f1-f5 五個函數是等價的,TypeScript 編譯器會把它們編譯成相同的 JavaScript 代碼(可以到 Playground 驗證)
// 一般的函數
let f1 = function(i: number): number { return i * i; };
// 根據返回值推斷函數返回類型
let f2 = function(i: number) { return i * i; };
// 胖箭頭表達式
let f3 = (i: number): number => { return i * i; };
// 根據返回值推斷返回類型的胖箭頭表達式
let f4 = (i: number) => { return i * i; };
// 根據返回值推斷返回類型的胖箭頭表達式, 省略花括號的同時,可以同時省去 return 關鍵字
let f5 = (i: number) => i * i;

// 接口是結構化的,任何具備接口中聲明的全部屬性的對象,都與該接口兼容
interface Person {
 name: string;
 // 使用 "?" 標識,表明該屬性是一個非必需屬性
 age?: number;
 // 函數
 move(): void;
}

// 實現 "Person" 接口的對象,當它具備 "name" 屬性和 "move" 方法之後可被視為一個 "Person"
let p: Person = { name: 'Bobby', move: () => {} };
// 帶可選屬性的對象
let validPerson: Person = { name: 'Bobby', age: 42, move: () => {} };
// 由於該對象 "age" 屬性的類型不是 "number" ,所以這不是一個 "Person"
let invalidPerson: Person = { name: 'Bobby', age: true };

// 接口同樣可以描述一個函數的類型
interface SearchFunc {
 (source: string, subString: string): boolean;
}
// 參數名並不重要,參數類型才是最重要的
let mySearch: SearchFunc;
mySearch = function(src: string, sub: string) {
 return src.search(sub) !== -1;
};

// 類 - 成員訪問權限默認都是公共的 (public)
class Point {
 // 成員屬性
 x: number;

 // 構造器 - 在構造器中使用 public/private 關鍵字修飾的變量,會被聲明為類的成員屬性。
 // 下面這個例子中,y 會像 x 一樣被聲明定義為類成員屬性,而不再需要額外代碼
 // 聲明時,同樣支持指定默認值

 constructor(x: number, public y: number = 0) { 
  this.x = x;
 }

 // 成員函數
 dist() { return Math.sqrt(this.x * this.x + this.y * this.y); }

 // 靜態成員
 static origin = new Point(0, 0);
}

let p1 = new Point(10 , 20);
let p2 = new Point(25); // y 為構造器中指定的默認值:0

// 繼承
class Point3D extends Point {
 constructor(x: number, y: number, public z: number = 0) {
  super(x, y); // 必須顯式調用父類的構造器
 }

 // 重寫父類中的 dist() 函數
 dist() {
  let d = super.dist();
  return Math.sqrt(d * d + this.z * this.z);
 }
}

// 模塊, "." 符號可以作為子模塊的分隔符
module Geometry {
 export class Square {
  constructor(public sideLength: number = 0) {
  }
  area() {
   return Math.pow(this.sideLength, 2);
  }
 }
}

let s1 = new Geometry.Square(5);

// 為模塊創建一個本地別名
import G = Geometry;

let s2 = new G.Square(10);

// 泛型
// 類
class Tuple<T1, T2> {
 constructor(public item1: T1, public item2: T2) {
 }
}

// 接口
interface Pair<T> {
 item1: T;
 item2: T;
}

// 以及函數
let pairToTuple = function<T>(p: Pair<T>) {
 return new Tuple(p.item1, p.item2);
};

let tuple = pairToTuple({ item1: 'hello', item2: 'world'});

// 引用定義文件
/// <reference path="jquery.d.ts" />

// 模板字符串(使用反引號的字符串)
// 嵌入變量的模板字符串
let name = 'Tyrone';
let greeting = `Hi ${name}, how are you?`;
// 有多行內容的模板字符串
let multiline = `This is an example
of a multiline string`;

參考資料

  • TypeScript 官網
  • TypeScript 語言規範説明書(pdf)
  • Anders Hejlsberg - TypeScript 介紹
  • GitHub 源碼
  • Definitely Typed - 類型定義倉庫

有建議?或者發現什麼錯誤?在Github上開一個 issue,或者發起 pull request !


原著 Philippe Vlérick ,並由 0 個好心人修改。

© 2022 Philippe Vlérick

Translated by: Shawn Zhang

本作品採用 CC BY-SA 3.0 協議進行許可。

user avatar lanlanjintianhenhappy 頭像
1 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.