本文翻譯自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編譯器就會報警——然而,如你所見,他們並不真的關心編譯器的那些警告。