JavaScript為弱引用類型語言,在聲明變量時不需要聲明變量類型,同時在聲明后的操作當中也可以隨意更改變量類型。而這種情況在類似于Java等強引用類型語言當中是不允許的。
TypeScript是JavaScript的超集,這意味著ts在兼容js所有語法的同時,對js進行了拓展,其中拓展的一步分就是在引用類型上變?yōu)榱藦娨妙愋驼Z言,ts的出現(xiàn)一定程度上彌補了js作為一門編程語言不夠嚴謹?shù)牡胤?,當然可能較為寬松的語法是js的一大特色,但在代碼運行上來講,很多時候這并非好事。ts能夠在使用中通過一些額外的信息使代碼更加健壯,在編寫過程中一旦代碼在ts中報錯或者警告我們就知道這里可能會存在隱患。有點類似于我們ES6當中的eslint,都屬于通過給我們編寫的代碼添加一定的約束來提高代碼的健壯性,讓我們盡量在開發(fā)過程中不要出錯。但ts的價值遠高于此,它能夠使js的語法和功能更加規(guī)范和完善,形成一整套體系。
使用前第一件事是全局安裝ts:安裝前確認nodejs環(huán)境安裝正確
npm install typescript -g
或者愛好使用yarn的話也可以
yarn global add typescript
安裝完成后可以新建.ts為后綴的文件,編寫ts代碼。但要注意一點是寫完之后要運行如下命令把代碼解析成js才可以運行:
舉例:
tsc 當前目錄/當前文件名.ts --outFile 輸出目錄/新文件名.js
這樣操作的問題是他每次運行命令都只會解析當前的代碼,也就是說如果在開發(fā)過程中你每當作了修改就需要不斷運行這段命令。
當然如果你嫌麻煩,不想每次更新寫完代碼都要重新運行命令進行編譯,也可以運行如下命令實時解析ts代碼:
tsc 當前文件夾目錄/* --outDir 輸出文件夾目錄
也可以更加規(guī)范,方便開發(fā)過程中配置,先運行:
tsc --init
這個時候當前目錄下就會出現(xiàn)tsconfig.json文件來進行具體的ts開發(fā)過程中的配置了。
比如上面的outDir命令就可以在文件當中找到,解開注釋并把目錄改成需要的目錄就可以了。
其他功能這里就先不一一列舉了。
解開outDir的注釋后,我們只需要運行如下命令就可以按照我們tsconfig.json文件的配置進行ts文件的實時解析了。
tsc --watch
ts通常情況下在變量聲明和引用不規(guī)范時會直接在控制臺報錯,這也是很多js開發(fā)者使用ts的第一個痛點:不熟悉變量如何聲明。
1.string,number,boolean類型:
let param:string = "字符串";//string類型
let param:number = 1;//number類型
let param:boolean = true;//boolean類型
2.array類型:
數(shù)組屬于復(fù)合數(shù)據(jù)類型,除了array本身的數(shù)據(jù)類型外,還要對內(nèi)部每一個元素的類型進行聲明。(當然在實際操作中數(shù)組內(nèi)部元素的類型可能會比較復(fù)雜,并未簡單數(shù)據(jù)類型,這種情況放在 5.any當中來講)
//方法一:(數(shù)組范型)
let array:Array<number> //聲明變量類型為數(shù)組,且內(nèi)部的每一個元素都為number
array = [1, 2, 3]
//方法二:
let array:number[] //聲明變量類型為數(shù)組,且內(nèi)部的每一個元素都為number
array = [1, 2, 3]
3.Tuple元組:
元組類型類似于數(shù)組,并可以定義數(shù)組類型里的每一個元素的類型。數(shù)組聲明時要統(tǒng)一規(guī)定內(nèi)部每一個元素的類型,而元組聲明時可以把每一個元素聲明為不同類型。
let tuple:[number, string];
tuple = [1, "hello"]
//ps:ts是不支持越界訪問的,比如當上面聲明的tuple只有兩個元素時,如果你訪問除這兩個元素之外的其他值的時候ts內(nèi)部將直接報錯。
console.log(tuple[3]) //ts終端報錯,編譯為js后會輸出undefined。
4.枚舉類型:
枚舉這種類型在js中比較陌生,有點類似卻又不同于js當中的類。也如同類一樣,在js當中一開始是沒有類這種類型的,我們在使用中都是用構(gòu)造函數(shù)來替代的。但諸如Java等主流的面向?qū)ο蟮恼Z言很多都是有類的,所以在ES6當中js也引入了類的概念。而枚舉在ts當中的引入也是同樣的道理。
//枚舉類型用enum聲明
enum Color {
Red, Yellow, Blue
}
//訪問
let r: Color = Color.Red;
console.log(r) // 0
//枚舉類型的賦值
enum Color {
Red = 2, Yellow = 4, Blue = 6
}
//訪問
let colorName:string = Color[6]
console.log(colorName) //Blue
5.any類型:自動類型推斷
這里很多用戶在使用ts的過程中并未聲明變量,但依然沒有報錯。這是因為在變量剛剛聲明的過程中ts自動進行變量類型檢測,聲明和使用的過程中如果變量類型保持一致,就不會報錯。但如果在使用過程中修改了變量類型,則會直接報錯。
這里還要注意一點就是我們的瀏覽器能夠運行的是js,而非ts,所以顯然我們暫時也沒有必要擔心ts會取代js地位的問題。ts是在我們開發(fā)過程中使用的語言,運行時需要編譯成js才能夠被瀏覽器或node執(zhí)行。也正因為其最終會被編譯為js,所以在使用ts的過程中即使出現(xiàn)變量聲明的錯誤,最終也不會影響代碼的執(zhí)行。但這就失去了我們使用ts的意義。
//自動類型推斷
let param = 1; //直接聲明不報錯
let param = 1;
param = '1'; //報錯: Type "1" is not assignable to type 'number'.ts
//自動類型推斷
//示例1
let param:number[]; //當我們聲明一個數(shù)組類型時
param.substr() //報錯,因為substr是字符串方法,當我們聲明數(shù)組時就默認當前變量只有數(shù)組相關(guān)方法,其他情況下可以舉一反三
很多應(yīng)用環(huán)境中,我們在聲明變量的時候可能并不確定這個變量是什么類型,尤其是在復(fù)合數(shù)據(jù)類型當中,這個時候我們可以把這個變量類型聲明成:any
//any類型
let param:any = 1;
param = '1';
param = true;
//都不會報錯
//并且當變量聲明為any時,這個變量就不會出現(xiàn)上方示例1當中的問題。
//當數(shù)組元素類型不確定時
let list: any[] = [1, '1', true];
6.void類型:
提到void,js當中我們可以進行這種操作javascript:void(0)用來阻止默認事件。
在ts中void則表示無返回值,與any類型相反,即任何類型都不可以。
//我們可以這么定義一個函數(shù)
function func():void { //此時這個函數(shù)不可以有任何返回值
return //可以return空或不return,不報錯。
}
//但不能return任何值
function func():void { //此時這個函數(shù)不可以有任何返回值
return 1 //報錯
}
//或者可以這樣聲明
let u:void = undefined; //總之就是不可以返回任何存在的值
7.聯(lián)合類型:
很多時候一個變量可能會出現(xiàn)幾種確定的變量類型,這個時候ts沒有必要把他們?nèi)悸暶鳛閍ny類型,這樣就失去了使用ts的意義。這個時候我們可以使用聯(lián)合類型。
let date:string | number | boolean;
date = 1
date = '1'
date = true //都可以
date = [] //報錯
//這種聲明方式常用于函數(shù)的參數(shù)類型聲明
這里要注意ts的自動數(shù)據(jù)類型推斷
let date:string | number | boolean;
date = '1'; //我們把date賦值為string類型
date = 1; //我們把date賦值為number類型
date.length; //報錯,因為ts推斷此時date為number類型,而length是string類型的方法。
date = '1'; //我們把date賦值為string類型
date.length; //正確
8.never類型:用于標記永遠不會存在的類型。多用于處理錯誤或者防止死循環(huán)。
因為實在不常用,這里就先不舉例了。
9.null undefined
這兩個類型是所有類型的子類型,早期版本和其他數(shù)據(jù)類型都不沖突,但新版本進行了嚴格化處理,不可以隨便賦給其他類型變量了,否則報錯。
10.interface 接口
我們可以直接定義一個接口,來形容我們聲明的類或?qū)ο蟮男螤睢?/p>
//定義Person約束,字段的數(shù)量和類型都不可更改。
interface Person {
name:string;
age:number;
}
//聲明tom時把Person約束賦給tom,無論多加字段、少寫字段、類型修改都會報錯。
let tom:Person = {
name:'Tom',
age:25
}
//也可以設(shè)置可選字段
interface Person {
name:string;
age?:number; //這樣age字段在聲明時可加可不加,都不會報錯。
}
//聲明tom時把Person約束賦給tom,無論多加字段、少寫字段、類型修改都會報錯。
let tom:Person = { //但是依然不允許自己添加屬性。
name:'Tom'
}
有時候我們在聲明對象的時候會有這種情況,我希望某個字段必填;某個字段選填,但一旦填寫則必須是某種類型;其他的字段都可填可不填,且不限制類型。這時候我們就可以用到索引簽名。
//索引簽名
interface Person {
name:string
age?:number
[propName: string]:any
}
let tom:Person = {
name:'Tom',
from:'US'
}
有時候我們還希望規(guī)范某些字段為只讀字段,不希望后續(xù)去做修改。
//readonly 只讀屬性
interface Person {
readonly name:string
}
let tom:Person = {
name:'Tom'
}
tom.name = 'Jerry' //Cannot assign to 'name' because it is a read-only property