TypeScript編譯器和編譯選項
1、編譯器
TypeScript編譯器是一段JavaScript程序,能夠對TypeScript代碼和JavaScript代碼進行靜態(tài)類型檢查,并且可以將TypeScript程序編譯為可執(zhí)行的JavaScript程序。TypeScript編譯器是自托管編譯器[插圖],它使用TypeScript語言進行開發(fā)。
TypeScript編譯器程序位于TypeScript語言安裝目錄下的lib文件夾中。TypeScript編譯器對外提供了一個命令行工具用來編譯TypeScript程序,它就是tsc命令。
1.1、安裝編譯器
安裝了Node.js之后,在命令行窗口中運行下列命令來全局安裝TypeScript語言:
npm install -g typescript
在不同的操作系統中,全局安裝的TypeScript會被安裝到不同的目錄下。例如,在Windows系統中TypeScript會被安裝到“%AppData%\npm”目錄下。
1.1.1、–help、–all
在成功地安裝了TypeScript后,我們就可以在命令行上使用tsc命令。按照慣例,可以使用“–help”?(簡寫為“-h”?)選項來顯示tsc命令的幫助信息。示例如下:
tsc --help
運行該命令將產生類似于如下的輸出結果:
Version 3.8.3
Syntax: tsc [options] [file...]
Examples: tsc hello.ts
tsc --outFile file.js file.ts
tsc @args.txt
tsc --build tsconfig.json
Options:
-h, --help Print this message.
-w, --watch Watch input files.
...在默認情況下,?“–help”選項僅會顯示基本的幫助信息。我們可以使用額外的“–all”選項來查看完整的幫助信息。示例如下:
tsc --help --all
1.1.2、–version
使用“–version”命令行選項能夠查看當前安裝的編譯器版本號。示例如下:
tsc --version Version 3.8.3
2、編譯程序
2.1、編譯單個文件
TypeScript編譯器最基本的使用方式是編譯單個文件。假設,當前工程目錄結構如下:
C:\app `-- index.ts
“index.ts”文件的內容如下:
function add(x: number, y: number): number {
return x + y;
}在“C:\app”目錄下運行tsc命令來編譯“index.ts”文件,示例如下:
tsc index.ts
默認情況下,編譯器會在“C:\app”目錄下生成編譯后的“index.js”文件,其內容如下:
function add(x, y) {
return x + y;
}當前工程目錄結構如下:
C:\app |-- index.js `-- index.ts
如果待編譯文件的文件名中帶有空白字符,如空格,那么就需要使用轉義符號“\”或者使用單、雙引號將文件名包圍起來。假設當前工程目錄結構如下:
C:\app `-- filename with spaces.ts
在“C:\app”目錄下運行tsc命令來編譯“filename withspaces.ts”文件。示例如下:
# 使用雙引號 tsc "filename with spaces.ts" # 使用單引號 tsc 'filename with spaces.ts' # 使用轉義符號 tsc filename\ with\ spaces.ts
2.2、編譯多個文件
TypeScript編譯器能夠同時編譯多個文件。我們可以在命令行上逐一列出待編譯的文件,也可以使用通配符來模糊匹配待編譯的文件。
假設當前工程目錄結構如下:
C:\app |-- index.ts `-- utils.ts
在“C:\app”目錄下運行tsc命令來編譯“index.ts”和“utils.ts”文件。示例如下:
tsc index.ts utils.ts
除此之外,還可以使用通配符來匹配待編譯的文件,支持的通配符包括:
- “*”匹配零個或多個字符,但不包含目錄分隔符。
- “?”匹配一個字符,但不包含目錄分隔符。
- “**/”匹配任意目錄及其子目錄。
在“C:\app”目錄下運行tsc命令并使用通配符來匹配當前目錄下的所有TypeScript文件。示例如下:
tsc *.ts
不論使用以上哪種方式來指定待編譯的文件,編譯器都會在“C:\app”目錄下生成編譯后的“index.js”文件和“utils.js”文件,工程目錄結構如下:
C:\app |-- index.js |-- index.ts |-- utils.js `-- utils.ts
2.3、–watch和-w
TypeScript編譯器提供了一種特殊的編譯模式,即觀察模式。在觀察模式下,編譯器會監(jiān)視文件的修改并自動重新編譯文件。觀察模式通過“–watch”?(簡寫為“-w”?)編譯選項來啟用。
假設當前工程目錄結構如下:
C:\app `-- index.ts
在“C:\app”目錄下運行tsc命令來編譯“index.ts”文件并啟用觀察模式。示例如下:
tsc index.ts --watch
運行tsc命令后,編譯器會編譯“index.ts”文件并進入觀察模式。在命令行窗口中能夠看到如下輸出消息:
[1:00:00 PM] Starting compilation in watch mode... [1:00:01 PM] Found 0 errors. Watching for file changes.
這時,如果我們修改“index.ts”文件并保存,編譯器會自動重新編譯“index.ts”文件。在命令行窗口中能夠看到如下輸出消息:
[1:00:10 PM] File change detected. Starting incremental compilation... [1:00:11 PM] Found 0 errors. Watching for file changes.
編譯器在重新編譯了“index.ts”文件之后依然會繼續(xù)監(jiān)視文件的修改。
2.4、–presserveWatchOutput
在觀察模式下,編譯器每次編譯文件之前都會清空命令行窗口中的歷史輸出信息。如果我們想保留每一次編譯的輸出信息,則可以使用“–preserveWatchOutput”編譯選項。示例如下:
tsc index.ts --watch --preserveWatchOutput
2、編譯選項
編譯選項是傳遞給編譯器程序的參數,使用編譯選項能夠改變編譯器的默認行為。在編譯程序時,編譯選項不是必須指定的。
本節(jié)不會介紹完整的編譯選項列表,而是會列舉出部分常用的編譯選項并介紹如何使用它們。
2.1、編譯選項風格
TypeScript編譯選項的命名風格包含以下兩種:
- 長名字風格,如“–help”?。
- 短名字風格,如“-h”?。
每一個編譯選項都有一個長名字,但是不一定有短名字。在TypeScript中,不論是長名字風格的編譯選項還是短名字風格的編譯選項均不區(qū)分大小寫,即“–help”?“–HELP”?“-h”?“-H”表示相同的含義。
長名字風格的編譯選項由兩個連字符和一個單詞詞組構成。提供長名字風格的命令行選項是推薦的做法。它有助于在不同程序之間保持一致的、具有描述性的選項名,從而提高開發(fā)者的使用體驗。
短名字風格的編譯選項名由單個連字符和單個字母構成。TypeScript編譯器僅針對一小部分常用的編譯選項提供了短名字。如果一個編譯選項具有短名字形式,那么該短名字通常為其長名字的首字母,例如“–help”編譯選項的短名字為“-h”?。
由于提供了短名字的編譯選項數量較少且十分常用,因此我們在表中列出了所有支持短名字風格的編譯選項。

2.2、使用編譯選項
在運行tsc命令時,可以在命令行上指定編譯選項。有一些編譯選項在使用時不必傳入參數,只需要寫出編譯選項名即可,例如“–version”?。示例如下:
tsc --version
我們也可以使用“–version”編譯選項的短名字形式“-v”?。示例如下:
tsc -v
實際上,每一個編譯選項都能夠接受一個參數值,只不過有一些編譯選項具有默認值,因此也可以省略傳入參數。在給編譯選項傳入參數時,需要將參數寫在編譯選項名之后,并以空格字符分隔。例如,?“–emitBOM”編譯選項接受true或false作為參數值。該編譯選項設置了編譯器在生成輸出文件時是否插入byte order mark(BOM)[插圖]。示例如下:
tsc --emitBOM true
如果編譯選項的參數值是布爾類型并且值為true,那么就可以省略傳入參數值。因此,上例中的命令等同于:
tsc --emitBOM
但如果編譯選項的參數值不是布爾類型的true或false,那么就不能省略參數值,必須在命令行上設置一個參數值。示例如下:
tsc --target ES5
如果想要同時使用多個編譯選項,那么在編譯選項之間使用空格分隔即可。示例如下:
tsc --version --locale zh-CN
此例中,同時使用了“–version”和“–locale”編譯選項。?“–locale”編譯選項能夠設置顯示信息時使用的區(qū)域和語言,它的可選值如下:
- 英語:en
- 捷克語:cs
- 德語:de
- 西班牙語:es
- 法語:fr
- 意大利語:it
- 日語:ja
- 韓語:ko
- 波蘭語:pl
- 葡萄牙語:pt-BR
- 俄語:ru
- 土耳其語:tr
- 簡體中文:zh-CN
2.3、嚴格類型檢查
TypeScript編譯器提供了兩種類型檢查模式,即嚴格類型檢查和非嚴格類型檢查。
非嚴格類型檢查是默認的類型檢查模式,該模式下的類型檢查比較寬松。在將已有的JavaScript代碼遷移到TypeScript時,通常會使用這種類型檢查模式,因為這樣做可以讓遷移工作更加順利地進行,不至于一時產生過多的錯誤。
在嚴格類型檢查模式下,編譯器會進行額外的類型檢查,從而能夠更好地保證程序的正確性。嚴格類型檢查功能使用一系列編譯選項來開啟。在開始一個新的工程時,強烈推薦啟用所有嚴格檢查編譯選項。對于已有的工程,則可以逐步啟用這些編譯選項。因為只有如此,才能夠最大限度地利用編譯器的靜態(tài)類型檢查功能。
2.3.1、–strict
“–strict”編譯選項是所有嚴格類型檢查編譯選項的“總開關”?。如果啟用了“–strict”編譯選項,那么就相當于同時啟用了下列編譯選項:
- –noImplicitAny
- –strictNullChecks
- –strictFunctionTypes
- –strictBindCallApply
- –strictPropertyInitialization
- –noImplicitThis
- –alwaysStrict
在實際工程中,我們可以先啟用“–strict”編譯選項,然后再根據需求禁用不需要的某些嚴格類型檢查編譯選項。這樣做有一個優(yōu)點,那就是在TypeScript語言發(fā)布新版本時可能會引入新的嚴格類型檢查編譯選項,如果啟用了“–strict”編譯選項,那么就會自動應用新引入的嚴格類型檢查編譯選項。
“–strict”編譯選項既可以在命令行上使用,也可以在“tsconfig.json”配置文件中使用。在命令行上使用該編譯選項,示例如下:
tsc --strict
在“tsconfig.json”配置文件中使用該編譯選項,示例如下:
{
"compilerOptions": {
"strict": true
}
}
上例的配置等同于如下“tsconfig.json”配置文件:
{
"compilerOptions": {
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"alwaysStrict": true
}
}2.3.2、–nolmplicitAny
若一個表達式沒有明確的類型注解并且編譯器又無法推斷出一個具體的類型時,那么它將被視為any類型。編譯器不會對any類型進行類型檢查,因此可能存在潛在的錯誤。
例如,下例中的函數參數str既沒有類型注解也無法推斷出具體類型,因此它的類型為any類型。不論我們使用哪種類型調用函數f都不會產生編譯錯誤,但如果實際參數不是string類型,那么在代碼運行時會產生錯誤。示例如下:
/**
* --noImplicitAny=false
*/
function f(str) {
// ~~~
// 類型為:any
console.log(str.substring(3));
}
f(42); // 運行時錯誤如果啟用了“–noImplicitAny”編譯選項,那么當表達式的推斷類型為any類型時將產生編譯錯誤。因此,上例中的代碼在啟用了“–noImplicitAny”編譯選項的情況下將產生編譯錯誤。示例如下:
/**
* --noImplicitAny=true
*/
function f(str) {
// ~~~
// 編譯錯誤!參數 'str' 隱式地成為 'any' 類型
console.log(str.substring(3));
}
f(42);2.3.3、–strictNullChecks
若沒有啟用“–strictNullChecks”編譯選項,編譯器在類型檢查時將忽略undefined值和null值。示例如下:
/**
* --strictNullChecks=false
*/
function f(str: string) {
console.log(str.substring(3));
}
// 以下均沒有編譯錯誤,但在運行時產生錯誤
f(undefined);
f(null);此例中,函數f期望傳入string類型的參數,并且在傳入undefined值和null值時,編譯器沒有產生錯誤。因為在沒有啟用“–strictNullChecks”編譯選項的情況下,當編譯器遇到undefined值和null值時會跳過類型檢查。而實際上,此例中的代碼在運行時會產生錯誤,因為在undefined值或null值上調用方法將拋出“TypeError”異常。
如果啟用了“–strictNullChecks”編譯選項,那么undefined值只能賦值給undefined類型(頂端類型、void類型除外)?,null值也只能賦值給null類型(頂端類型除外)?,兩者都明確地擁有了各自的類型。因此,上例中的代碼在該編譯選項下會產生編譯錯誤。示例如下:
/**
* --strictNullChecks=true
*/
function f(str: string) {
console.log(str.substring(3));
}
f(undefined);
//~~~~~~~~~
//編譯錯誤!'undefined' 不能賦值給 'string' 類型的參數
f(null);
//~~~~
//編譯錯誤!'null' 不能賦值給 'string' 類型的參數2.3.4、–strictFunctionTypes
該編譯選項用于配置編譯器對函數類型的類型檢查規(guī)則。
如果啟用了“–strictFunctionTypes”編譯選項,那么函數參數類型與函數類型之間是逆變關系。
如果禁用了“–strictFunctionTypes”編譯選項,那么函數參數類型與函數類型之間是相對寬松的雙變關系。
不論是否啟用了“–strictFunctionTypes”編譯選項,函數返回值類型與函數類型之間始終是協變關系。
2.3.5、–strictBindCallApply
“Function.prototype.call”?“Function.prototype.bind”?“Function.prototype.apply”是JavaScript語言中函數對象上的內置方法。這三個方法都能夠綁定函數調用時的this值。例如,下例中的6、7、8行將調用函數f時的this值設置成了對象“{ name: ‘ts’ }”?:
function f(this: { name: string }, x: number, y: number) {
console.log(this.name);
console.log(x + y);
}
f.apply({ name: 'ts' }, [1, 2]);
f.call({ name: 'ts' }, 1, 2);
f.bind({ name: 'ts' })(1, 2);如果沒有啟用“–strictBindCallApply”編譯選項,那么編譯器不會對以上三個內置方法進行類型檢查。雖然函數聲明f中定義了this的類型以及參數x和y的類型,但是傳入任何類型的實際參數都不會產生編譯錯誤。示例如下:
/**
* --strictBindCallApply=false
*/
function f(this: { name: string }, x: number, y: number) {
console.log(this.name);
console.log(x + y);
}
// 下列語句均沒有編譯錯誤
f.apply({}, ['param']);
f.call({}, 'param');
f.bind({})('param');如果啟用了“–strictBindCallApply”編譯選項,那么編譯器將對以上三個內置方法的this類型以及參數類型進行嚴格的類型檢查。示例如下:
/**
* --strictBindCallApply=true
*/
function f(this: Window, str: string) {
return this.alert(str);
}
f.call(document, 'foo');
// ~~~~~~~~
// 編譯錯誤!'document' 類型的值不能賦值給 'window' 類型的參數
f.call(window, false);
// ~~~~~
// 編譯錯誤!'false' 類型的值不能賦值給 'string' 類型的參數
f.apply(document, ['foo']);
// ~~~~~~~~
// 編譯錯誤!'document' 類型的值不能賦值給 'window' 類型的參數
f.apply(window, [false]);
// ~~~~~
// 編譯錯誤!'false' 類型的值不能賦值給 'string' 類型的參數
f.bind(document);
// ~~~~~~~~
// 編譯錯誤!'document' 類型的值不能賦值給 'window' 類型的參數
// 正確的用法
f.call(window, 'foo');
f.apply(window, ['foo']);
f.bind(window);2.3.6、–strictPropertyInitialization
該編譯選項用于配置編譯器對類屬性的初始化檢查。
如果啟用了“–strictPropertyInitialization”編譯選項,那么當類的屬性沒有進行初始化時將產生編譯錯誤。類的屬性既可以在聲明時直接初始化,例如下例中的屬性x,也可以在構造函數中初始化,例如下例中的屬性y。如果一個屬性沒有使用這兩種方式之一進行初始化,那么會產生編譯錯誤,例如下例中的屬性z。示例如下:
/**
* -- strictPropertyInitialization=true
*/
class Point {
x: number = 0;
y: number;
z: number; // 編譯錯誤!屬性 'z' 沒有初始值,也沒有在構造函數中初始化
constructor() {
this.y = 0;
}
}若沒有啟用“–strictPropertyInitialization”編譯選項,那么上例中的代碼不會產生編譯錯誤。也就是說,允許未初始化的屬性z存在。
使用該編譯選項時需要注意一種特殊情況,有時候我們會在構造函數中調用其他方法來初始化類的屬性,而不是在構造函數中直接進行初始化。目前,編譯器無法識別出這種情況,依舊會認為類的屬性沒有被初始化,進而產生編譯錯誤。我們可以使用“!”類型斷言來解決這個問題,示例如下:
/**
* -- strictPropertyInitialization=true
*/
class Point {
x: number; // 編譯錯誤:屬性 'x' 沒有初始值,也沒有在構造函數中初始化
y!: number; // 正確
constructor() {
this.initX();
this.initY();
}
private initX() {
this.x = 0;
}
private initY() {
this.y = 0;
}
}2.3.7、–noImplicitThis
與“–noImplicitAny”編譯選項類似,在啟用了“–noImplicitThis”編譯選項時,如果程序中的this值隱式地獲得了any類型,那么將產生編譯錯誤。示例如下:
/**
* -- noImplicitThis=true
*/
class Rectangle {
width: number;
height: number;
constructor(width: number, height: number) {
this.width = width;
this.height = height;
}
getAreaFunctionWrong() {
return function () {
return this.width * this.height;
// ~~~~ ~~~~
// 編譯錯誤:'this' 隱式地獲得了 'any' 類型
// 因為不存在類型注解
};
}
getAreaFunctionCorrect() {
return function (this: Rectangle) {
return this.width * this.height;
};
}
}2.3.8、–alwaysStrict
ECMAScript 5引入了一個稱為嚴格模式[插圖]的新特性。在全局JavaScript代碼或函數代碼的開始處添加““usestrict””指令就能夠啟用JavaScript嚴格模式。在模塊和類中則會始終啟用JavaScript嚴格模式。注意,JavaScript嚴格模式不是本節(jié)所講的TypeScript嚴格類型檢查模式。
在JavaScript嚴格模式下,JavaScript有著更加嚴格的語法要求和一些新的語義。例如,implements、interface、let、package、private、protected、public、static和yield都成了保留關鍵字;在函數的形式參數列表中,不允許出現同名的形式參數等。
若啟用了“–alwaysStrict”編譯選項,則編譯器總是以JavaScript嚴格模式的要求來檢查代碼,并且在編譯生成JavaScript代碼時會在代碼的開始位置添加““use strict””指令。示例如下:
/**
* --alwaysStrict=true
*/
function outer() {
if (true) {
function inner() {
// ~~~~~
// 編譯錯誤!當編譯目標為'ES3'或'ES5'時,
// 在嚴格模式下的語句塊中不允許使用函數聲明
}
}
}此例中,只有在啟用了“–alwaysStrict”編譯選項時,第6行代碼才會產生編譯錯誤。因為在JavaScript嚴格模式下,語句塊中不允許出現函數聲明。
2.4、編譯選項列表
隨著TypeScript版本的更新,提供的編譯選項列表也會有所變化。例如,一些編譯選項會被廢棄,也會有一些新加入的編譯選項。推薦讀者到TypeScript官方網站上的“Compiler Options”頁面[插圖]中了解最新的編譯選項列表。
官方網站的Compiler Options頁面地址:https://www.typescriptlang.org/docs/handbook/compiler-options.html。
到此這篇關于TypeScript編譯器和編譯選項的文章就介紹到這了,更多相關TypeScript編譯器和編譯選項內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
asp(javascript)全角半角轉換代碼 dbc2sbc
asp與javascript 全角半角處理代碼2009-08-08

