TypeScript 詳解之 TypeScript 的類型系統(tǒng)

TypeScript 繼承了 JavaScript 的類型,在這個(gè)基礎(chǔ)上,定義了一套自己的類型系統(tǒng)。

基本類型

概述

JavaScript 語(yǔ)言(注意,不是 TypeScript)將值分成8種類型。

  • boolean
  • string
  • number
  • bigint
  • symbol
  • object
  • undefined
  • null

TypeScript 繼承了 JavaScript 的類型設(shè)計(jì),以上8種類型可以看作 TypeScript 的基本類型。

注意,上面所有類型的名稱都是小寫字母,首字母大寫的NumberStringBoolean等在 JavaScript 語(yǔ)言中都是內(nèi)置對(duì)象,而不是類型名稱。

另外,undefined 和 null 既可以作為值,也可以作為類型,取決于在哪里使用它們。

這8種基本類型是 TypeScript 類型系統(tǒng)的基礎(chǔ),復(fù)雜類型由它們組合而成。

以下是它們的簡(jiǎn)單介紹。

boolean 類型

boolean類型只包含truefalse兩個(gè)布爾值。

const x:boolean = true;
const y:boolean = false;

上面示例中,變量xy就屬于 boolean 類型。

string 類型

string類型包含所有字符串。

const x:string = 'hello';
const y:string = `${x} world`;

上面示例中,普通字符串和模板字符串都屬于 string 類型。

number 類型

number類型包含所有整數(shù)和浮點(diǎn)數(shù)。

const x:number = 123;
const y:number = 3.14;
const z:number = 0xffff;

上面示例中,整數(shù)、浮點(diǎn)數(shù)和非十進(jìn)制數(shù)都屬于 number 類型。

bigint 類型

bigint 類型包含所有的大整數(shù)。

const x:bigint = 123n;
const y:bigint = 0xffffn;

上面示例中,變量xy就屬于 bigint 類型。

bigint 與 number 類型不兼容。

const x:bigint = 123; // 報(bào)錯(cuò)
const y:bigint = 3.14; // 報(bào)錯(cuò)

上面示例中,bigint類型賦值為整數(shù)和小數(shù),都會(huì)報(bào)錯(cuò)。

注意,bigint 類型是 ES2020 標(biāo)準(zhǔn)引入的。如果使用這個(gè)類型,TypeScript 編譯的目標(biāo) JavaScript 版本不能低于 ES2020(即編譯參數(shù)target不低于es2020)。

symbol 類型

symbol 類型包含所有的 Symbol 值。

const x:symbol = Symbol();

上面示例中,Symbol()函數(shù)的返回值就是 symbol 類型。

symbol 類型的詳細(xì)介紹,參見《Symbol》一章。

object 類型

根據(jù) JavaScript 的設(shè)計(jì),object 類型包含了所有對(duì)象、數(shù)組和函數(shù)。

const x:object = { foo: 123 };
const y:object = [1, 2, 3];
const z:object = (n:number) => n + 1;

上面示例中,對(duì)象、數(shù)組、函數(shù)都屬于 object 類型。

undefined 類型,null 類型

undefined 和 null 是兩種獨(dú)立類型,它們各自都只有一個(gè)值。

undefined 類型只包含一個(gè)值undefined,表示未定義(即還未給出定義,以后可能會(huì)有定義)。

let x:undefined = undefined;

上面示例中,變量x就屬于 undefined 類型。兩個(gè)undefined里面,第一個(gè)是類型,第二個(gè)是值。

null 類型也只包含一個(gè)值null,表示為空(即此處沒有值)。

const x:null = null;

上面示例中,變量x就屬于 null 類型。

注意,如果沒有聲明類型的變量,被賦值為undefinednull,它們的類型會(huì)被推斷為any

let a = undefined;   // any
const b = undefined; // any

let c = null;        // any
const d = null;      // any

如果希望避免這種情況,則需要打開編譯選項(xiàng)strictNullChecks

// 打開編譯設(shè)置 strictNullChecks
let a = undefined;   // undefined
const b = undefined; // undefined

let c = null;        // null
const d = null;      // null

上面示例中,打開編譯設(shè)置strictNullChecks以后,賦值為undefined的變量會(huì)被推斷為undefined類型,賦值為null的變量會(huì)被推斷為null類型。

包裝對(duì)象類型

包裝對(duì)象的概念

JavaScript 的8種類型之中,undefinednull其實(shí)是兩個(gè)特殊值,object屬于復(fù)合類型,剩下的五種屬于原始類型(primitive value),代表最基本的、不可再分的值。

  • boolean
  • string
  • number
  • bigint
  • symbol

上面這五種原始類型的值,都有對(duì)應(yīng)的包裝對(duì)象(wrapper object)。所謂“包裝對(duì)象”,指的是這些值在需要時(shí),會(huì)自動(dòng)產(chǎn)生的對(duì)象。

'hello'.charAt(1) // 'e'

上面示例中,字符串hello執(zhí)行了charAt()方法。但是,在 JavaScript 語(yǔ)言中,只有對(duì)象才有方法,原始類型的值本身沒有方法。這行代碼之所以可以運(yùn)行,就是因?yàn)樵谡{(diào)用方法時(shí),字符串會(huì)自動(dòng)轉(zhuǎn)為包裝對(duì)象,charAt()方法其實(shí)是定義在包裝對(duì)象上。

這樣的設(shè)計(jì)大大方便了字符串處理,省去了將原始類型的值手動(dòng)轉(zhuǎn)成對(duì)象實(shí)例的麻煩。

五種包裝對(duì)象之中,symbol 類型和 bigint 類型無法直接獲取它們的包裝對(duì)象(即Symbol()BigInt()不能作為構(gòu)造函數(shù)使用),但是剩下三種可以。

  • Boolean()
  • String()
  • Number()

以上三個(gè)構(gòu)造函數(shù),執(zhí)行后可以直接獲取某個(gè)原始類型值的包裝對(duì)象。

const s = new String('hello');
typeof s // 'object'
s.charAt(1) // 'e'

上面示例中,s就是字符串hello的包裝對(duì)象,typeof運(yùn)算符返回object,不是string,但是本質(zhì)上它還是字符串,可以使用所有的字符串方法。

注意,String()只有當(dāng)作構(gòu)造函數(shù)使用時(shí)(即帶有new命令調(diào)用),才會(huì)返回包裝對(duì)象。如果當(dāng)作普通函數(shù)使用(不帶有new命令),返回就是一個(gè)普通字符串。其他兩個(gè)構(gòu)造函數(shù)Number()Boolean()也是如此。

包裝對(duì)象類型與字面量類型

由于包裝對(duì)象的存在,導(dǎo)致每一個(gè)原始類型的值都有包裝對(duì)象和字面量?jī)煞N情況。

'hello' // 字面量
new String('hello') // 包裝對(duì)象

上面示例中,第一行是字面量,第二行是包裝對(duì)象,它們都是字符串。

為了區(qū)分這兩種情況,TypeScript 對(duì)五種原始類型分別提供了大寫和小寫兩種類型。

  • Boolean 和 boolean
  • String 和 string
  • Number 和 number
  • BigInt 和 bigint
  • Symbol 和 symbol

其中,大寫類型同時(shí)包含包裝對(duì)象和字面量?jī)煞N情況,小寫類型只包含字面量,不包含包裝對(duì)象。

const s1:String = 'hello'; // 正確
const s2:String = new String('hello'); // 正確

const s3:string = 'hello'; // 正確
const s4:string = new String('hello'); // 報(bào)錯(cuò)

上面示例中,String類型可以賦值為字符串的字面量,也可以賦值為包裝對(duì)象。但是,string類型只能賦值為字面量,賦值為包裝對(duì)象就會(huì)報(bào)錯(cuò)。

建議只使用小寫類型,不使用大寫類型。因?yàn)榻^大部分使用原始類型的場(chǎng)合,都是使用字面量,不使用包裝對(duì)象。而且,TypeScript 把很多內(nèi)置方法的參數(shù),定義成小寫類型,使用大寫類型會(huì)報(bào)錯(cuò)。

const n1:number = 1;
const n2:Number = 1;

Math.abs(n1) // 1
Math.abs(n2) // 報(bào)錯(cuò)

上面示例中,Math.abs()方法的參數(shù)類型被定義成小寫的number,傳入大寫的Number類型就會(huì)報(bào)錯(cuò)。

上一小節(jié)說過,Symbol()BigInt()這兩個(gè)函數(shù)不能當(dāng)作構(gòu)造函數(shù)使用,所以沒有辦法直接獲得 symbol 類型和 bigint 類型的包裝對(duì)象,因此SymbolBigInt這兩個(gè)類型雖然存在,但是完全沒有使用的理由。

Object 類型與 object 類型

TypeScript 的對(duì)象類型也有大寫Object和小寫object兩種。

Object 類型

大寫的Object類型代表 JavaScript 語(yǔ)言里面的廣義對(duì)象。所有可以轉(zhuǎn)成對(duì)象的值,都是Object類型,這囊括了幾乎所有的值。

let obj:Object;

obj = true;
obj = 'hi';
obj = 1;
obj = { foo: 123 };
obj = [1, 2];
obj = (a:number) => a + 1;

上面示例中,原始類型值、對(duì)象、數(shù)組、函數(shù)都是合法的Object類型。

事實(shí)上,除了undefinednull這兩個(gè)值不能轉(zhuǎn)為對(duì)象,其他任何值都可以賦值給Object類型。

let obj:Object;

obj = undefined; // 報(bào)錯(cuò)
obj = null; // 報(bào)錯(cuò)

上面示例中,undefinednull賦值給Object類型,就會(huì)報(bào)錯(cuò)。

另外,空對(duì)象{}Object類型的簡(jiǎn)寫形式,所以使用Object時(shí)常常用空對(duì)象代替。

let obj:{};

obj = true;
obj = 'hi';
obj = 1;
obj = { foo: 123 };
obj = [1, 2];
obj = (a:number) => a + 1;

上面示例中,變量obj的類型是空對(duì)象{},就代表Object類型。

顯然,無所不包的Object類型既不符合直覺,也不方便使用。

object 類型

小寫的object類型代表 JavaScript 里面的狹義對(duì)象,即可以用字面量表示的對(duì)象,只包含對(duì)象、數(shù)組和函數(shù),不包括原始類型的值。

let obj:object;

obj = { foo: 123 };
obj = [1, 2];
obj = (a:number) => a + 1;
obj = true; // 報(bào)錯(cuò)
obj = 'hi'; // 報(bào)錯(cuò)
obj = 1; // 報(bào)錯(cuò)

上面示例中,object類型不包含原始類型值,只包含對(duì)象、數(shù)組和函數(shù)。

大多數(shù)時(shí)候,我們使用對(duì)象類型,只希望包含真正的對(duì)象,不希望包含原始類型。所以,建議總是使用小寫類型object,不使用大寫類型Object

還有 61% 的精彩內(nèi)容
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
支付 ¥9.99 繼續(xù)閱讀
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,179評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,444評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,948評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,185評(píng)論 0 287
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,717評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,602評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,794評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,045評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評(píng)論 1 281
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,414評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,750評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容