小心TypeScript編寫出無用的代碼

本文翻譯自The Daily WTF網站,原作者的大意是TypeScript相比JavaScript確實有很多優勢,但是這個優勢其實是編譯器帶來的。在編寫TS代碼的時候應當重視編譯器的警告,因爲有些代碼轉換成JS後可能並不會有錯誤,但是實際上因爲JS缺少TS的一些特性,可能會導致代碼運行出問題。

TypeScript相比JavaScript有一定的優勢。編譯時檢查能夠發現很多代碼編寫的錯誤,相比瀏覽器而言發展更快,與最新的行業標準更匹配(編譯器將那些與瀏覽器解釋轉化討厭的細節全部搞定了),而且TS還有更方便好用的語法糖。
如果你在使用TS,你可以使用編譯器發現代碼中很多醜陋的問題,而你要做的就是把那些標紅的錯誤修改掉。或者,你可以像昆塔斯(Quintus)的同事那樣,就像,呃,下面的代碼。

/**
 * Container holding definition information.
 *
 * @param String version
 * @param String date

 */
export class Definition {
  private id: string;
  private name: string;
  constructor(private version, private data) {}

  /**
   * get the definition version
   *
   * @return String version
   */
  getVersion() {
    return this.id;
  }

  /**
   * get the definition date
   *
   * @return String date
   */
  getDate() {
    return this.name;
  }
}

現在,如果你想在TS的環境中運行這段代碼,你會發現在編譯和轉換成JS過程中,編譯器合理地指出了一堆警示。然而,如果你用命令行工具tsc編譯,默認設置下卻沒有任何警示。

因此,如果TypeScript代碼寫得不好,編譯器工具可以告訴你代碼的問題所在,但是前提是你得要求編譯器工具按你的要求檢查。

不管怎麼說,很容易理解這個糟糕的代碼會發生什麼:這顯然是通過複製/粘貼完成的編碼。代碼定義了一個擁有id和name屬性的類。複製/粘貼的時候卻弄成了version和date,然後可能是代碼還沒改完,中途被什麼事打斷了。他們也像模像樣地檢查了代碼,但是卻沒人發現——直到昆塔斯站在旁邊的時候。

再來聊聊這段代碼,你會發現id和name是私有屬性,構造器又定義了另外兩個屬性(通過構造器進行關聯):私有的version和data參數。因此,當調用構造函數的時候,實際上初始化了根本沒有對應訪問方法的兩個私有成員。確實是有成員訪問方法,但是實際使用卻是id和name的,而id和name既沒有在構造方法初始化,也沒有外部設置的入口。

由於TS編譯成了JS,而JS是沒有private這個關鍵字的,因此編譯成JS並不會有任何警告。我猜想這段代碼最終胎死腹中,並沒有真正派上用場。如果需要用的話,我敢打賭是下面這樣的。

let f = new Definition();
f.id = "1.0.1"
f.name = "28-OCT-2020"
…
let ver = f.getVersion();

這段代碼可以按照原先的開發者預期那樣正常運行,但是如果他們這麼做的話,TS編譯器就會報警——然而,如你所見,他們並不真的關心編譯器的那些警告。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章