使用TypeScript類型注解的方法詳解
類型注解
TypeScript提供了很多數(shù)據(jù)類型,通過類型對變量進行限制,稱之為類型注解,使用類型注解后,就不能夠隨意變更變量的類型。
以下代碼定義了一個字符串類型的變量,如果把它更改為數(shù)字類型時,代碼編譯階段就會直接報錯,提示 “Type ‘number’ is not assignable to type ‘string’”。
這樣保證變量的數(shù)據(jù)類型是固定的,那么它所能使用的方法也是確定的,不會出現(xiàn)變量本來是字符串,調(diào)用了 toUpperCase方法,后來在未測試到的某場景無意中把它改為數(shù)字類型后,調(diào)用 toUpperCase 直接報錯的情況。
類型推導(dǎo)
當(dāng)變量沒有寫數(shù)據(jù)類型時,ts內(nèi)部會進行"類型推導(dǎo)",通過上下文賦值語句判斷出該變量的數(shù)據(jù)類型,所以在類型注解較為簡單時且其能準(zhǔn)確自動推導(dǎo)出類型時,不寫類型注解對代碼質(zhì)量也沒有影響。
TS和JS共有的數(shù)據(jù)類型
TypeScript包含了JavaScript所擁有的數(shù)據(jù)類型,string
、number
、symbol
、array
、boolean
、undefined
、null
、object
。
其中,array 在定義的時候需要加上數(shù)組中的每一個數(shù)據(jù)的類型,是字符串、數(shù)字還是對象,這就使得數(shù)組中不可以寫多種數(shù)據(jù)類型,如果有需要寫多種數(shù)據(jù)類型的情況,可以直接不加類型注解,會自動進行【類型推導(dǎo)】。
let str: string = "string"; let num: number = 0; let sym: symbol = Symbol("sym"); let arr1: string[] = ['alice', 'kiki', 'heidi'] let arr2: object[] = [{ name: 'alice'}] let arr3: number[] = [1, 2, 3] let flag: boolean = false; let und: undefined = undefined; let nu: null = null; let user = { name: "alice" };
上面的對象user也是沒有加類型注解的,因為如果定義為 object 類型,無法獲取和修改user對象上的屬性。
這是因為user是object類型,但object類型上沒有name屬性,所以編譯階段會直接報錯,所以對于對象可以不加類型注解,讓其自動進行類型推導(dǎo)。
TS獨有的數(shù)據(jù)類型
此外TypeScirpt還增加了很多JavaScript沒有的數(shù)據(jù)類型
any
any是一個 “萬金油” 的數(shù)據(jù)類型,表示 “任意” 數(shù)據(jù)類型,當(dāng)變量的類型不確定且有可能發(fā)生變化時,可以定義為 any,此時變量的數(shù)據(jù)類型可以被隨意更改,這其實會帶來一些安全隱患。
比如下面的代碼,將字符串當(dāng)作函數(shù)使用,undefined使用數(shù)字的方法。因為是any類型,類型有可能被改成字符串、數(shù)字、布爾值,所以這樣的代碼不會被ts檢測出問題,但在運行時肯定是會報錯的。
let message: any = "message"; message(); message = 0; message = undefined; message.toFixed();
unknown
當(dāng)一個變量的類型暫時不確定時,可以使用unknown用來限制其類型。
let flag = true let result: unknown; if (flag) { result = 'Hello World' } else { result = 888 }
它和any有些像,但區(qū)別在于unknown是不能被賦值給除了any和unknown類型的變量,這樣使得unknown的值不能被亂用到其它地方。
void
當(dāng)函數(shù)沒有返回值時,實際上返回的就是 undefined,void 通常用來表示函數(shù)返回值為 undefined 或者 null。
以下形式都是可以的
function add(): void {} function sub(): void { return undefined } function mul(): void { return null }
當(dāng)存在返回值時,編譯是會報錯的。
never
never 表示永遠(yuǎn)不會存在的類型,如果函數(shù)為死循環(huán)或者拋出異常時可以使用。
function foo(): never { while (true) {} } function catchError(): never { throw new Error("error"); }
當(dāng)我們封裝工具函數(shù)時,開始規(guī)定的函數(shù)入?yún)?string 類型,但可能后續(xù)在其它人開發(fā)過程中,增加了 number 類型,為了避免維護時忘記對該類型數(shù)據(jù)進行處理,可以把入?yún)①x值給 never 類型的變量,使得編譯不通過來防止開發(fā)者邏輯疏漏。
tuple
tuple 意思是元組,和數(shù)組比較相似,但元組和數(shù)組還是存在以下區(qū)別。
- 數(shù)組中元素數(shù)據(jù)類型建議是一致的,當(dāng)數(shù)據(jù)類型不一致時考慮放到元組或者對象。
- 元組中每個元素都有自己的特性,可以通過索引值獲取。
// 數(shù)組 const array: string[] = ["alice", "kiki"]; // 元組 const tuple: [string, number] = ["alice", 20];
函數(shù)參數(shù)和返回值
聲明函數(shù)時,在函數(shù)的每個參數(shù)后添加類型注解,以聲明函數(shù)接受的參數(shù)類型,限制參數(shù)類型、參數(shù)個數(shù)。
在函數(shù)列表后面定義的類型注解,用于限制函數(shù)返回值類型的。
// 限制參入類型 function foo(message: string, no: number) {} // 限制返回值 function baz(message: string): string { return "string"; }
當(dāng)入?yún)㈩愋?個數(shù)沒有達(dá)到注解要求時,編譯會標(biāo)紅以提醒。
對象類型、可選類型、聯(lián)合類型 也都是可以用于規(guī)定函數(shù)入?yún)⒌摹?/p>
- 對象類型,定義對象中每個參數(shù)的數(shù)據(jù)類型
- 可選類型,用 ?表示,意味著該參數(shù)是非必傳的,必須寫在必選類型后面
- 聯(lián)合類型,用 | 表示,A | B 意味著入?yún)㈩愋褪茿和B中的任意一個
function getPoint(point: { x: number; y: number; z?: number }) {} getPoint({ x: 10, y: 20 }); getPoint({ x: 10, y: 20, z: 30 }); function printId(id: string | number) {} printId(1); printId("alice"); function foo(message?: string) {} foo("message"); foo();
當(dāng)需要規(guī)定的類型比較長時,可以通過 type 關(guān)鍵字來定義類型別名
同時參數(shù)類型為【可選類型】可以理解該參數(shù)類型與 undefined 的【聯(lián)合類型】,以下兩個參數(shù)的入?yún)⒈举|(zhì)上是一樣的
function foo(message?: string) {} foo("message"); foo(); function baz(message: string | undefined) {} baz("message"); baz(undefined);
類型斷言
有時候TypeScirpt獲取到的類型是比較廣泛的,這個時候可以使用類型斷言,通過關(guān)鍵字 as 定義具體數(shù)據(jù)類型。
比如以下定義了兩個類,Student 繼承自 Person 類,且擁有自己的 studying 方法,定義sayHello方法,要求入?yún)㈩愋蜑镻erson,此時創(chuàng)建Student的實例對象student,并調(diào)用sayHello方法,傳入student。
class Person {} class Student extends Person { studying(){} } function sayHello(p: Person){} const student = new Student() sayHello(student)
以上代碼在編譯的時候是沒有問題的,但如果在sayHello方法中想要調(diào)用Student實例對象的studying,是不可以的,因為雖然傳入的參數(shù)是Student的實例對象,但它在TypeScript中只能被檢測為Person類型,而Person上是沒有studying方法的。
要想正確調(diào)用,需要使用類型斷言規(guī)定入?yún)⒌膶嶋H類型
function sayHello(p: Person){ (p as Student).studying() }
非空類型斷言
通過 !符號來使不能通過編譯的代碼不被標(biāo)紅提醒,但如果運行階段代碼存在問題,仍然是會拋出錯誤的。
字面量
通過const定義的變量的數(shù)據(jù)類型為字面量類型,字面量里的值就是該變量賦值的內(nèi)容。
通過字面量類型,可用于規(guī)定變量的選擇范圍,比如 flex 布局的 direction 可以選擇 row 或者 colums
type DirectionType = "row" | "colums"; let direction: DirectionType = "row"; direction = "colums";
當(dāng)變量賦值為它類型注解中所沒有包含的內(nèi)容時,是會標(biāo)紅提醒的。
類型縮小
類型縮小表示當(dāng)變量數(shù)據(jù)類型的范圍比較大時,我們可以通過 if 、switch 、in 、typeof、instanceof 等方式進行判斷來縮小的變量的類型,以達(dá)到更精準(zhǔn)的操作。
比如一個函數(shù)的參數(shù)類型可能為 string 和 number,直接獲取 length 屬性 是會報錯的。因為只有 string 類型的變量可以獲取到 length,但在 number 類型上是不存在的,所以此時可以通過 typeof 來判斷入?yún)㈩愋?,這個判斷步驟也稱為"類型保護"。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
js實現(xiàn)網(wǎng)頁自動刷新可制作節(jié)日倒計時效果
這篇文章主要介紹了通過js實現(xiàn)的網(wǎng)頁自動刷新,利用此功能可制作節(jié)日倒計時效果,需要的朋友可以參考下2014-05-05JavaScript使用function定義對象并調(diào)用的方法
這篇文章主要介紹了JavaScript使用function定義對象并調(diào)用的方法,實例分析了javascript中function定義及使用對象與方法的相關(guān)技巧,需要的朋友可以參考下2015-03-03簡單實用的js調(diào)試logger組件實現(xiàn)代碼
開發(fā)js組件的時間調(diào)試總是麻煩的,最常用的就是用alert或者debugger來測試js的運行狀態(tài)。2010-11-11JavaScript請求后臺數(shù)據(jù)的常用方法匯總
這篇文章主要介紹了JavaScript請求后臺數(shù)據(jù)的幾種常用方式,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-06-06Javascript對象中關(guān)于setTimeout和setInterval的this介紹
Javascript對象中關(guān)于setTimeout和setInterval的this介紹,需要的朋友可以參考下2012-07-07微信小程序封裝網(wǎng)絡(luò)請求和攔截器實戰(zhàn)步驟
這篇文章主要介紹了微信小程序封裝網(wǎng)絡(luò)請求和攔截器實戰(zhàn)步驟,這樣可以提高開發(fā)效率,減少代碼重復(fù),同時也可以提高代碼的可維護性和可讀性2023-03-03JavaScript實現(xiàn)手寫call/apply/bind的示例代碼
這篇文章主要為大家詳細(xì)介紹了JavaScript實現(xiàn)手寫call/apply/bind的方法,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)JavaScript有一定的幫助,需要的可以參考一下2023-02-02微信小程序wx.request實現(xiàn)后臺數(shù)據(jù)交互功能分析
這篇文章主要介紹了微信小程序wx.request實現(xiàn)后臺數(shù)據(jù)交互功能,分析微信小程序wx.request在后臺數(shù)據(jù)交互過程中遇到的問題與相關(guān)的解決方法,需要的朋友可以參考下2017-11-11