不用擔心 TypeScript 編譯後會很難除錯

由於 TypeScript 是編譯語言,很多人擔心該如何 debug Angular,尤其是 TypeScript 編譯沒錯,但在瀏覽器執行卻錯了,但因為 TypeScript 已經編譯成 JavaScript,我該怎麼知道錯在 TypeScript 哪一行呢?

Version


Angular CLI 1.1.2
Angular 4.2.3

Runtime Error


src/app/app.component.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { Component, OnInit } from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'app';

ngOnInit(): void {
this.title = undefined;

if (this.title.length > 0) {
console.log('app');
}
}
}

title 設為 undefined 後,再取得 title.length 當然會錯誤,不過 TypeScript 在編譯階段不會報錯。

debug000

若 Angular 執行階段錯誤,在 Chrome 的 Developer Tools 的 Console 會出現錯誤訊息。

Chrome 明確顯示 Cannot read property 'length' of undefined,因為 titleundefined

重要的是,Chrome 明確告訴我們錯在 app.component.ts,是 TypeScript 而不是 JavaScript。

debug001

app.component.ts 後,會進入 TypeScript 程式碼錯的那一行,因此不用擔心是編譯過的 JavaScript 而無從 debug。

不是已經編譯成 JavaScript 了嗎?為什麼 Chrome 知道錯在 TypeScript 哪一行?

debug005

事實上在 ng serve 編譯時,還同時產生了各 js 對應的 js.map,Chrome 就是靠這些 map 檔得知錯誤的 JavaScript 對應到 TypeScript 哪一行。

可是我不希望正式上線主機也包含這些 map 檔怎麼辦?

debug006

ng build —-prod ,則編譯後將不包含 map 檔,且 js size 也小很多,可安心放在正式上線主機上。

關於 undefined


關於 undefined 問題,其實 TypeScript 另有解法,只要啟動 StrictNullCheck,就可由 TypeScript 編譯器幫我們擋掉這個錯誤。

debug002

tsconfig.json 加上 strictNullChecks: true,強迫 TypeScript 檢查 nullundefined 的型別檢查。

debug003

Language service 會提出警告,不可將 undefined 指定給 string 型別。

debug004

TypeScript 實際編譯也是會報錯。

啟動 StrictNullCheck 後,TypeScript 會將 nullundefined 視為一種型別,因此不可將 nullundefined 指定給 string 型別。

Conclusion


  • 其實我一開始也很擔心 TypeScript 經過編譯後,會很難 debug,但所幸有 map 檔配套方案,讓 Chrome 能從 JavaScript 對應到 TypeScript,直接將錯誤顯示在 TypeScript 的正確行數。
  • 實務上 Angular 的除錯,第一步是看 TypeScript 是否編譯錯誤,第二部是用 Chrome Developer Tools 看是否有執行上的錯誤,然後對應到相對應的 TypeScript 檔案。
  • Angular 為 Chrome 提供非常清楚的 TypeScript 錯誤訊息,不用擔心編譯過的 JavaScript 看不懂而無從 debug。
2017-07-05