iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 3
0
Software Development

今晚我想來點 Express 佐 MVC 分層架構系列 第 3

[今晚我想來點 Express 佐 MVC 分層架構] DAY 03 - 為什麼是 TypeScript?

上一篇的小結有提到我會採用 TypeScript 作為開發語言,但是什麼原因要捨棄 JavaScript 呢?我們就來了解一下要如何用 TypeScript 解決幾個 JavaScript 的痛點。

由於網路上已有許多 TypeScript 的資源,本系列文就不再寫基本語法的教學。

型別系統

JavaScript 是一個弱型別語言,而 TypeScript 可以說是強型別的 JavaScript。在型別上就有以下幾個痛點是可以用 TypeScript 來解決的:

理解上的誤差

在撰寫帶參數的函式時,不會強制要求參數一定要是何種型別,比如說,有個函式用來將所有參數相加並返回其加總:

const sum = (...args) => args.reduce((a, c) => a + c);

此時很難判斷這個函式究竟是用來加總數字?還是用來字串相加?這兩種結果截然不同,卻都適用於此函式,試想今天是一個大型專案,一個函式多種用法是否很容易產生問題呢?更具體一點的舉例:小明都用 sum(...args) 來處理加總數字、小華都用 sum(...args) 處理字串相加、阿呆都看心情用,這時候可能會有 理解上的誤差 ,當問題產生的時候,就會很難找出錯誤。

const sum = (...args) => args.reduce((a, c) => a + c);

// 都適用於此函式
console.log(sum(1, 2, 3));
console.log(sum(1, 2, '3'));

在編輯器上看看吧!

那麼 TypeScript 如何解決這個問題呢?就是替變數加上型別定義,此時,這個函式只接受數字型別的參數,可以解決理解上的誤差:

const sum = (...args: number[]) => args.reduce((a, c) => a + c);

console.log(sum(1, 2, 3, 4, 5));
// 會顯示錯誤並編譯不過
console.log(sum(1, 2, 3, 4, '5'));

在編輯器上看看吧!

無法辨識

試想今天有一個函式是要處理個人資料用的,所以把個資傳入函式進行處理:

const responseBasicInfo = info => {
  // info 裡面有什麼屬性???
};

如上方範例所示,我們無法在第一時間知道這個參數裡面到底有什麼屬性,造成 無法辨識 的問題,這時候只好去看資料庫回傳的資料格式長什麼樣子然後寫 JSDoc...

JSDoc 是一種 JavaScript 的註解風格,部分編輯器可以透過撰寫 JSDoc 來顯示變數的型別

/**
 * @param {{ name: string, email: string, phone: string }} info - profile.
 */
const responseBasicInfo = info => {
  const { name, email, phone } = info;
  console.log(name, email, phone);
};

const profile = {
  name: 'HAO',
  email: 'test@test.com',
  phone: '0987654321'
};

responseBasicInfo(profile);

在編輯器上看看吧!

如果用 TypeScript 的話,可以事先定義好資料的 model,並定義參數的型別為該 model:

class ProfileModel {
  public name: string;
  public email: string;
  public phone: string;

  constructor(data) {
    this.name = data.name;
    this.email = data.email;
    this.phone = data.phone;
  }
}

const responseBasicInfo = (info: ProfileModel) => {
  const { name, email, phone } = info;
  console.log(name, email, phone);
};

const profile: ProfileModel = {
  name: 'HAO',
  email: 'test@test.com',
  phone: '0987654321'
};

responseBasicInfo(profile);

在編輯器上看看吧!

公有與私有

在過去,JavaScript 的世界裡是沒有公有與私有概念的,需要用一些手段來實作出私有概念:

_ 即私有

這是很常見的「宣告」方式,只要開頭有個 _ 就「當作」私有屬性及方法 ,但其實還是可以被外部使用:

class Pig {

  constructor(weight) {
    // 問體重不禮貌,所以宣告成私有屬性
    this._weight = weight;
  }
  
  eat() {
    this._weight++;
    console.log('Oink!');
  }

}

試想被宣告出來的豬會開心嗎?只是我們說好不能偷看而已,但他們的體重還是可以被知道耶!

const shyPig = new Pig(130);
console.log(shyPig._weight); // 130

在編輯器上看看吧!

這樣的宣告方式其實沒有什麼約束力,若團隊中有人誤用的話,那就失去私有的意義了!

用閉包

確實用閉包可以解決這個問題:

class Pig {
  constructor(weight) {
    let _weight = weight;
    this.eat = () => {
      _weight++;
      console.log('Oink!');
    }
  }
}

此時害羞的豬體重只有自己知道:

const shyPig = new Pig(130);
console.log(shyPig._weight); // undefined

在編輯器上看看吧!

但這樣類別的方法有使用到私有屬性的話,就不能在 prototype 中宣告,會造成 程式碼不整潔 的問題。

TypeScript 能解!

TypeScript 可以像 C# 等語言一樣直接宣告為 publicprivate 以及 protected,直觀且存取範圍分明:

class Pig {
  private weight: number;

  constructor(weight) {
    this.weight = weight;
  }

  public eat() {
    this.weight++;
    console.log('Oink!');
  }

}

const shyPig = new Pig(130);
console.log(shyPig.weight);

在編輯器上看看吧!

小結

在開發大型系統的時候,不論是理解上的落差、無法辨識型別或是存取權,都很容易導致系統產生問題,因此,我會採用 TypeScript 而不是 JavaScript 。下一篇將會帶著大家進入 Express 的世界,敬請期待!


上一篇
[今晚我想來點 Express 佐 MVC 分層架構] DAY 02 - 軟體架構之 MVC
下一篇
[今晚我想來點 Express 佐 MVC 分層架構] DAY 04 - 建置專案
系列文
今晚我想來點 Express 佐 MVC 分層架構30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言