深入理解TypeScript 類型兼容性
我們學(xué)習(xí)類型兼容性,就是在學(xué)習(xí) TypeScript 在一個(gè)類型能否賦值給其他類型的規(guī)則。本節(jié)將會(huì)詳細(xì)介紹 TypeScript 在函數(shù)、枚舉、類和泛型中的類型兼容性規(guī)則。
1. 解釋
類型兼容性用于確定一個(gè)類型是否能賦值給其他類型。
TypeScript 的類型檢查機(jī)制都是為了讓開發(fā)者在編譯階段就可以直觀的發(fā)現(xiàn)代碼書寫問題,養(yǎng)成良好的代碼規(guī)范從而避免很多低級(jí)錯(cuò)誤。
let address: string = 'Baker Street 221B' let year: number = 2010 address = year // Error
代碼解釋: 第 3 行,類型 ‘number’ 不能賦值給類型 ‘string’。
2. 結(jié)構(gòu)化
TypeScript 類型兼容性是基于結(jié)構(gòu)類型的;結(jié)構(gòu)類型只使用其成員來描述類型。
TypeScript 結(jié)構(gòu)化類型系統(tǒng)的基本規(guī)則是,如果 x 要兼容 y,那么 y 至少具有與 x 相同的屬性。比如:
interface User { name: string, year: number } let protagonist = { name: 'Sherlock·Holmes', year: 1854, address: 'Baker Street 221B' } let user: User = protagonist // OK
代碼解釋: 接口 User 中的每一個(gè)屬性在 protagonist 對(duì)象中都能找到對(duì)應(yīng)的屬性,且類型匹配。另外,可以看到 protagonist 具有一個(gè)額外的屬性 address,但是賦值同樣會(huì)成功。
3. 比較兩個(gè)函數(shù)
相對(duì)來講,在比較原始類型和對(duì)象類型的時(shí)候是比較容易理解的,難的是如何判斷兩個(gè)函數(shù)是否兼容。判斷兩個(gè)函數(shù)是否兼容,首先要看參數(shù)是否兼容,第二個(gè)還要看返回值是否兼容。
3.1 函數(shù)參數(shù)
先看一段代碼示例:
let fn1 = (a: number, b: string) => {} let fn2 = (c: number, d: string, e: boolean) => {} fn2 = fn1 // OK fn1 = fn2 // Error
代碼解釋:
第 4 行,將 fn1 賦值給 fn2 成立是因?yàn)椋?/p>
- fn1 的每個(gè)參數(shù)均能在 fn2 中找到對(duì)應(yīng)類型的參數(shù)
- 參數(shù)順序保持一致,參數(shù)類型對(duì)應(yīng)
- 參數(shù)名稱不需要相同
第 5 行,將 fn2 賦值給 fn1 不成立,是因?yàn)?fn2 中的必須參數(shù)必須在 fn1 中找到對(duì)應(yīng)的參數(shù),顯然第三個(gè)布爾類型的參數(shù)在 fn1 中未找到。
參數(shù)類型對(duì)應(yīng)即可,不需要完全相同:
let fn1 = (a: number | string, b: string) => {} let fn2 = (c: number, d: string, e: boolean) => {} fn2 = fn1 // OK
代碼解釋: fn1 的第一個(gè)參數(shù)是 number 和 string 的聯(lián)合類型,可以對(duì)應(yīng) fn2 的第一個(gè)參數(shù)類型 number,所以第 4 行賦值正常。
3.2 函數(shù)返回值
創(chuàng)建兩個(gè)僅是返回值類型不同的函數(shù)
代碼解釋: 最后一行,函數(shù) x() 缺少 location 屬性,所以報(bào)錯(cuò)。
類型系統(tǒng)強(qiáng)制源函數(shù)的返回值類型必須是目標(biāo)函數(shù)返回值類型的子類型。由此可以得出如果目標(biāo)函數(shù)的返回值類型是 void,那么源函數(shù)返回值可以是任意類型:
let x : () => void let y = () => 'mybj' x = y // OK
4. 枚舉的類型兼容性
枚舉與數(shù)字類型相互兼容:
enum Status { Pending, Resolved, Rejected } let current = Status.Pending let num = 0 current = num num = current
不同枚舉類型之間是不兼容的:
enum Status { Pending, Resolved, Rejected } enum Color { Red, Blue, Green } let current = Status.Pending current = Color.Red // Error
5. 類的類型兼容性
類與對(duì)象字面量和接口的兼容性非常類似,但是類分實(shí)例部分和靜態(tài)部分。
比較兩個(gè)類類型數(shù)據(jù)時(shí),只有實(shí)例成員會(huì)被比較,靜態(tài)成員和構(gòu)造函數(shù)不會(huì)比較。
class Animal { feet!: number constructor(name: string, numFeet: number) { } } class Size { feet!: number constructor(numFeet: number) { } } let a: Animal let s: Size a = s! // OK s = a // OK
代碼解釋: 類 Animal 和類 Size 有相同的實(shí)例成員 feat
屬性,且類型相同,構(gòu)造函數(shù)參數(shù)雖然不同,但構(gòu)造函數(shù)不參與兩個(gè)類類型比較,所以最后兩行可以相互賦值。
類的私有成員和受保護(hù)成員會(huì)影響兼容性。 允許子類賦值給父類,但是不能賦值給其它有同樣類型的類。
class Animal { protected feet!: number constructor(name: string, numFeet: number) { } } class Dog extends Animal {} let a: Animal let d: Dog a = d! // OK d = a // OK class Size { feet!: number constructor(numFeet: number) { } } let s: Size a = s! // Error
代碼解釋:
第 13 行,子類可以賦值給父類。
第 14 行,父類之所以能夠給賦值給子類,是因?yàn)樽宇愔袥]有成員。
最后一行,因?yàn)轭?Animal 中的成員 feet 是受保護(hù)的,所以不能賦值成功。
6. 泛型的類型兼容性
泛型的類型兼容性根據(jù)其是否被成員使用而不同。先看一段代碼示例:
interface Empty<T> {} let x: Empty<number> let y: Empty<string> x = y! // OK
上面代碼里,x 和 y 是兼容的,因?yàn)樗鼈兊慕Y(jié)構(gòu)使用類型參數(shù)時(shí)并沒有什么不同。但是當(dāng)泛型被成員使用時(shí):
interface NotEmpty<T> { data: T } let x: NotEmpty<number> let y: NotEmpty<string> x = y! // Error
代碼解釋: 因?yàn)榈?4 行,泛型參數(shù)是 number 類型,第 5 行,泛型參數(shù)是 string 類型,所以最后一行賦值失敗。
如果沒有指定泛型類型的泛型參數(shù),會(huì)把所有泛型參數(shù)當(dāng)成 any 類型比較
7. 小結(jié)
要充分利用 TypeScript 的類型檢查機(jī)制規(guī)范代碼,減少一些不必要的錯(cuò)誤,這也是我們使用 TypeScript 的初衷。
到此這篇關(guān)于深入理解TypeScript 類型兼容性的文章就介紹到這了,更多相關(guān)TypeScript類型兼容性內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS一個(gè)簡(jiǎn)單的注冊(cè)頁面實(shí)例
下面小編就為大家?guī)硪黄狫S一個(gè)簡(jiǎn)單的注冊(cè)頁面實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09JS擴(kuò)展類,克隆對(duì)象與混合類實(shí)例分析
這篇文章主要介紹了JS擴(kuò)展類,克隆對(duì)象與混合類,通過自定義extend,clone與augment函數(shù)實(shí)例分析了類的擴(kuò)展,對(duì)象的克隆與混合類相關(guān)實(shí)現(xiàn)與使用技巧,需要的朋友可以參考下2016-11-11Javascript中查找不以XX字符結(jié)尾的單詞示例代碼
我在寫這篇文章之前花了2個(gè)多小時(shí)在弄正則表達(dá)式,下為大家介紹下具體的實(shí)現(xiàn)思路,感興趣的朋友可以參考下2013-10-10JavaScript實(shí)現(xiàn)對(duì)下拉列表值進(jìn)行排序的方法
這篇文章主要介紹了JavaScript實(shí)現(xiàn)對(duì)下拉列表值進(jìn)行排序的方法,實(shí)例分析了javascript對(duì)下拉列表元素的遍歷與排序?qū)崿F(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07JavaScript判斷變量是否為數(shù)組的方法(Array)
這篇文章主要介紹了JavaScript判斷變量是否為數(shù)組的方法(Array),涉及到j(luò)avascript 數(shù)組 變量相關(guān)知識(shí),感興趣的朋友一起學(xué)習(xí)吧2016-02-02利用JS實(shí)現(xiàn)獲取當(dāng)前系統(tǒng)電量情況
在前端瀏覽器中我們可以通過使用JavaScript的navigator.getBattery()方法來獲取當(dāng)前系統(tǒng)的電池情況,本文將介紹如何使用這個(gè)API以及它在實(shí)際應(yīng)用中的使用,需要的可以參考下2023-12-12探究Javascript模板引擎mustache.js使用方法
這篇文章主要為大家介紹了Javascript模板引擎mustache.js使用方法,mustache.js是一個(gè)簡(jiǎn)單強(qiáng)大的Javascript模板引擎,使用它可以簡(jiǎn)化在js代碼中的html編寫,壓縮后只有9KB,非常值得在項(xiàng)目中使用,感興趣的小伙伴們可以參考一下2016-01-01基于js實(shí)現(xiàn)微信發(fā)送好友如何分享到朋友圈、微博
微信瀏覽器內(nèi)置了javascript私有對(duì)象WeixinJSBridge,可以實(shí)現(xiàn)發(fā)送給朋友、分享到朋友圈、分享到微博等功能,本篇文章給大家介紹基于js實(shí)現(xiàn)微信發(fā)送給朋友如何分享到朋友圈、微博,感興趣的朋友一起學(xué)習(xí)吧2015-11-11