Template String是 TypeScript 1.4 起加入的超好用功能(跟 C# Interpolated Strings 字串插值一樣,是用過就上癮的好物),今天發現一個問題 - Template String 內含的中文字元會被強制轉成 \uxxxx。(這種表示法術語叫 Unicode Escape Sequences)
例如以下範例:
var t2 = `ABC-中文-${n}`;
會變成:
var t2 = "ABC-\u4E2D\u6587-" + n;
想爬文找出避免轉換的做法,在 TypeScript Github 找到一則討論: Incorrect compilation of template strings containing Unicode characters
有不少開發者也發現了這個問題,認為 TypeScript 沒必要把所有非 ASCII 字元都換成 \uxxxx 格式。這個問題被認定是個 Bug,而開發團隊成員 DanielRosenwasser 提出解釋:
The reason I didn't preserve the original text when I implemented this was to avoid re-scanning the string when performing emit. We basically take the internal textual representation and call something that's basically an augmented JSON.stringify. This is good because it replaces newlines with \n,
However, the function takes a conservative approach and uses a unicode escape if something falls outside of ASCII. We take advantage of this if you ever use an extended unicode escapes in all strings.
For instance, the string "\u{12345} också" will get rewritten to
"\uD808\uDF45 ocks\u00E5"
in ES5 instead of"\uD808\uDF45 också"
So what you're noticing is that this function does a teensy bit too much.Also, given the fact that TypeScript can _finally_ assume the existence of JSON.stringify, this fix is probably a LOT easier.
DanielRosenwasser 提到不保留原始文字是為了避免注入過程需要重新掃瞄字串,程式內部借用了類似 JSON.stringify() 的函式進行轉換(好處是換行符號會換成 \n),該函式為求保險將 ASCII 字元表(0x00-0x7f)以外的字元通通換成 \uxxxx,雖然如此一舉解決罕用 Unicode 字元的轉換,但該函式的轉換範圍太過火,產生我們觀察到的後遺症。
好消息是 TypeScript 終於能假設 JSON.stringify 一定存在,這問題將比較容易修復,而壞消息是這個 Bug 被排在 Future 清單,何時會修正不得而知。
我唯一想到的 Workaround 是改寫成 `ABC-${"中文內容"}`,很醜且中英文穿插時會很噁心,算不上什麼好法子。
所幸,這在實務上不算嚴重問題。 TypeScript 預設會產生 js.map:
故實際偵錯時中斷點是停在 .ts 原始碼,可直接看到原始中文,.js 中文變成編碼的困擾不大。
只有一點要注意: 當你試圖在 js 搜尋中文關鍵字,要有可能會撲空的心理準備。