欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

TypeScript中類(lèi)型兼容性的示例詳解

 更新時(shí)間:2022年08月22日 09:51:02   作者:CUGGZ  
JavaScript是一門(mén)弱類(lèi)型語(yǔ)言,它對(duì)類(lèi)型是弱校驗(yàn),所以才有了TypeScript。本文就來(lái)和大家一起看看TypeScript的類(lèi)型兼容性的概念和分類(lèi),需要的可以參考一下

JavaScript 是一門(mén)弱類(lèi)型語(yǔ)言,它對(duì)類(lèi)型是弱校驗(yàn),正因?yàn)檫@個(gè)特點(diǎn),所以才有了TypeScript這個(gè)強(qiáng)類(lèi)型語(yǔ)言系統(tǒng)的出現(xiàn),來(lái)彌補(bǔ)類(lèi)型檢查的短板。TypeScript在實(shí)現(xiàn)類(lèi)型強(qiáng)校驗(yàn)的同時(shí),還要滿(mǎn)足 JavaScript 靈活的特點(diǎn),所以就有了類(lèi)型兼容性這個(gè)概念。了解類(lèi)型兼容性可以避免在實(shí)際的開(kāi)發(fā)中出現(xiàn)一些低級(jí)錯(cuò)誤。下面就來(lái)看看類(lèi)型兼容性的概念和分類(lèi)。

1. 類(lèi)型兼容性的概念

所謂的類(lèi)型兼容性用于確定一個(gè)類(lèi)型是否能賦值給其他類(lèi)型。TypeScript中的類(lèi)型兼容性是基于結(jié)構(gòu)類(lèi)型的,結(jié)構(gòu)類(lèi)型是一種只使用其成員來(lái)描述類(lèi)型的方式。其基本原則是,如果 x 要兼容 y,那么 y 至少要具有與 x 相同的屬性。

下面來(lái)看一個(gè)例子,構(gòu)建一個(gè) Teacher 類(lèi) ,然后聲明一個(gè)接口 Student,Student 的屬性 Teacher 都有,而且還多了其他的屬性,這種情況下 Student 就兼容了 Teacher

class?Teacher?{
????constructor(public?weight:?number,?public?name:?string,?public?job:?string)?{
????
????}
}</code><code>interface?Student?{
????name:?string
????weight:?number
}</code><code>let?x:?Student;
x?=?new?Teacher(120,?'TS',?'teacher')?//??

如果反過(guò)來(lái),Teacher 并沒(méi)有兼容 Student,因?yàn)?nbsp;Student 的屬性比 Person 少一個(gè)。

2. 特殊類(lèi)型的類(lèi)型兼容性

先來(lái)看看 TypeScript 中一些特殊類(lèi)型的類(lèi)型兼容性。

(1)any

any 類(lèi)型可以賦值給除了 never 之外的任意其他類(lèi)型,反過(guò)來(lái)其他類(lèi)型也可以賦值給 any。也就是說(shuō) any 可以兼容除了 never 之外的所有類(lèi)型,同時(shí)也可以被所有的類(lèi)型兼容。

let?any:?any;

let?a:?number?=?any;???????//??
let?b:?{}?=?any;???????????//??
let?b:?()?=>?number?=?any;?//??

(2)never

never 類(lèi)型可以賦值給任何其他類(lèi)型,但不能被其他任何類(lèi)型賦值。

let?never:?never?=?(()?=>?{
??throw?Error('never');
})();

let?a:?number?=?never;???????//??
let?b:?()?=>?number?=?never;?//??
let?c:?{}?=?never;???????????//??

可以看到,這里將 never 類(lèi)型賦值給了 number、函數(shù)、對(duì)象類(lèi)型,都是沒(méi)有問(wèn)題的。

(3)unknown

unknown 和 never 的特性是相反的,即不能把 unknown 賦值給除了 any 之外的任何其他類(lèi)型,但其他類(lèi)型都可以賦值給 unknown

let?unknown:?unknown;

const?a:?number?=?unknown;???????//?不能將類(lèi)型“unknown”分配給類(lèi)型“number”。
const?b:?()?=>?number?=?unknown;?//?不能將類(lèi)型“unknown”分配給類(lèi)型“()?=> number”。
const?c:?{}?=?unknown;???????????//?不能將類(lèi)型“unknown”分配給類(lèi)型“{}”。

可以看到,當(dāng)把 unknown 類(lèi)型賦值給 number、函數(shù)、對(duì)象類(lèi)型時(shí),都報(bào)錯(cuò)了,這就是因?yàn)轭?lèi)型之間不能兼容。

3. 函數(shù)類(lèi)型的類(lèi)型兼容性

函數(shù)的類(lèi)型兼容性主要包括以下六個(gè)方面:

(1)參數(shù)數(shù)量

函數(shù)參數(shù)數(shù)量要想兼容,需要滿(mǎn)足一個(gè)要求:如果將函數(shù) y 賦值為 x,那么要求 x 中的每個(gè)參數(shù)都應(yīng)在 y 中有對(duì)應(yīng),也就是 x 的參數(shù)個(gè)數(shù)小于等于 y 的參數(shù)個(gè)數(shù)

let?x?=?(a:?number)?=>?0;
let?y?=?(b:?number,?c:?string)?=>?0;

上面定義的兩個(gè)函數(shù),如果進(jìn)行賦值的話(huà),來(lái)看下兩種情況的結(jié)果:

y?=?x;??//??

將 x 賦值給 y 是可以的,因?yàn)?x 的參數(shù)個(gè)數(shù)小于等于 y 的參數(shù)個(gè)數(shù),而至于參數(shù)名是否相同是無(wú)所謂的。

而將 y 賦值給 x 就不可以了:

x?=?y;?//?不能將類(lèi)型“(b: number, c: string)?=> number”分配給類(lèi)型“(a: number)?=> number”。

這里 y 的參數(shù)個(gè)數(shù)要大于 x,所以報(bào)錯(cuò)了。

(2)函數(shù)參數(shù)類(lèi)型

除了參數(shù)數(shù)量,參數(shù)的類(lèi)型也需要對(duì)應(yīng):

let?x?=?(a:?number)?=>?0;
let?y?=?(b:?string)?=>?0;
x?=?y;?// error 不能將類(lèi)型“(b: string)?=> number”分配給類(lèi)型“(a: number)?=> number”。

可以看到,x 和 y 兩個(gè)函數(shù)的參數(shù)個(gè)數(shù)和返回值都相同,只是參數(shù)類(lèi)型對(duì)不上,所以也是不行的。

(3)剩余參數(shù)和可選參數(shù)

當(dāng)要被賦值的函數(shù)參數(shù)中包含剩余參數(shù)(…args)時(shí),賦值的函數(shù)可以用任意個(gè)數(shù)參數(shù)代替,但是類(lèi)型需要對(duì)應(yīng):

const?getNum?=?(
??arr:?number[],
??callback:?(...args:?number[])?=>?number
):?number?=>?{
??return?callback(...arr);
};

getNum(
??[1,?2],
??(...args:?number[]):?number?=>?args.length?//?返回參數(shù)的個(gè)數(shù)
);

剩余參數(shù)其實(shí)可以看做無(wú)數(shù)個(gè)可選參數(shù),所以在兼容性方面是差不多的。

再來(lái)看一個(gè)可選參數(shù)和剩余參數(shù)結(jié)合的例子:

//?第二個(gè)參數(shù)callback是一個(gè)函數(shù),函數(shù)的第二個(gè)參數(shù)為可選參數(shù)
const?getNum?=?(
??arr:?number[],
??callback:?(arg1:?number,?arg2?:?number)?=>?number?
):?number?=>?{
??return?callback(...arr);?//?error?應(yīng)有?1-2?個(gè)參數(shù),但獲得的數(shù)量大于等于?0
};

這里因?yàn)?nbsp;arr 可能為空數(shù)組,如果為空數(shù)組則…arr不會(huì)給callback傳入任何實(shí)際參數(shù),所以這里就會(huì)報(bào)錯(cuò)。如果換成return callback(arr[0], …arr)就沒(méi)問(wèn)題了。

(4)參數(shù)雙向協(xié)變

函數(shù)參數(shù)雙向協(xié)變即參數(shù)類(lèi)型無(wú)需絕對(duì)相同

let?funcA?=?function(arg:?number?|?string):?void?{};
let?funcB?=?function(arg:?number):?void?{};
//?funcA?=?funcB?和?funcB?=?funcA都可以

這里 funcA 和 funcB 的參數(shù)類(lèi)型并不完全一樣,funcA 的參數(shù)類(lèi)型為一個(gè)聯(lián)合類(lèi)型 number | string,而 funcB 的參數(shù)類(lèi)型為 number | string 中的 number,這兩個(gè)函數(shù)也是兼容的。

(5)返回值類(lèi)型

函數(shù)返回值的類(lèi)型也是要對(duì)應(yīng)的:

let?x?=?(a:?number):?string?|?number?=>?0;
let?y?=?(b:?number)?=>?"a";
let?z?=?(c:?number)?=>?false;
x?=?y;?//??
x?=?z;?//?不能將類(lèi)型“(c:?number)?=>?boolean”分配給類(lèi)型“(a:?number)?=>?string?|?number”

這里 x 函數(shù)的返回值是聯(lián)合類(lèi)型,既可以是 string 類(lèi)型也可以是 number 類(lèi)型。而 y 的返回值類(lèi)型是 number 類(lèi)型,參數(shù)個(gè)數(shù)和類(lèi)型也沒(méi)問(wèn)題,所以可以賦值給 x。而 z 的返回值類(lèi)型 false 并不是 string 也不是 number,所以不能賦值。

(6)函數(shù)重載

帶有重載的函數(shù),要求被賦值的函數(shù)的每個(gè)重載都能在用來(lái)賦值的函數(shù)上找到對(duì)應(yīng)的簽名:

function?merge(arg1:?number,?arg2:?number):?number;?//?merge函數(shù)重載的一部分
function?merge(arg1:?string,?arg2:?string):?string;?//?merge函數(shù)重載的一部分
function?merge(arg1:?any,?arg2:?any)?{?//?merge函數(shù)實(shí)體
??return?arg1?+?arg2;
}
function?sum(arg1:?number,?arg2:?number):?number;?//?sum函數(shù)重載的一部分
function?sum(arg1:?any,?arg2:?any):?any?{?//?sum函數(shù)實(shí)體
??return?arg1?+?arg2;
}
let?func?=?merge;
func?=?sum;?//?error?不能將類(lèi)型“(arg1:?number,?arg2:?number)?=>?number”分配給類(lèi)型“{?(arg1:?number,?arg2:?number):?number;?(arg1:?string,?arg2:?string):?string;?}”

sum 函數(shù)的重載缺少參數(shù)都為string返回值為string的情況,與merge函數(shù)不兼容,所以賦值時(shí)就會(huì)報(bào)錯(cuò)。

4. 枚舉的類(lèi)型兼容性

數(shù)字枚舉成員類(lèi)型與數(shù)字類(lèi)型是互相兼容的:

enum?Status?{
??On,
??Off
}
let?s?=?Status.On;
s?=?1;
s?=?3;

雖然 Status.On 的值是 0,但是因?yàn)閿?shù)字枚舉成員類(lèi)型和數(shù)值類(lèi)型是互相兼容的,所以這里給s賦值為 3 是沒(méi)問(wèn)題的。但是不同枚舉值之間是不兼容的:

enum?Status?{
??On,
??Off
}
enum?Color?{
??White,
??Black
}
let?s?=?Status.On;
s?=?Color.White;?//?不能將類(lèi)型“Color.White”分配給類(lèi)型“Status”。

雖然 Status.On 和 Color.White 的值都是 0,但它們是不兼容的。

字符串枚舉成員類(lèi)型和字符串類(lèi)型是不兼容的:

enum?Status?{
??On?=?'on',
??Off?=?'off'
}
let?s?=?Status.On
s?=?'TypeScript'?//?不能將類(lèi)型"TypeScript"分配給類(lèi)型“Status”

這里會(huì)報(bào)錯(cuò),因?yàn)樽址置媪款?lèi)型'TypeScript'Status.On是不兼容的。

4. 類(lèi)類(lèi)型的類(lèi)型兼容性

比較兩個(gè)類(lèi)的類(lèi)型兼容性時(shí),只有實(shí)例成員和方法會(huì)相比較,類(lèi)的靜態(tài)成員和構(gòu)造函數(shù)不進(jìn)行比較

class?Animal?{
??static?age:?number;
??constructor(public?name:?string)?{}
}

class?People?{
??static?age:?string;
??constructor(public?name:?string)?{}
}

class?Food?{
??constructor(public?name:?number)?{}
}

let?a:?Animal;
let?p:?People;
let?f:?Food;
a?=?p;?//?ok
a?=?f;?//?不能將類(lèi)型“Food”分配給類(lèi)型“Animal”。

Animal類(lèi)和People類(lèi)都有一個(gè)age靜態(tài)屬性,它們都定義了實(shí)例屬性name,類(lèi)型是string。把類(lèi)型為Peoplep賦值給類(lèi)型為Animala是沒(méi)有問(wèn)題的,因?yàn)轭?lèi)類(lèi)型比較兼容性時(shí),只比較實(shí)例的成員,這兩個(gè)變量雖然類(lèi)型是不同的類(lèi)類(lèi)型,但是它們都有相同字段和類(lèi)型的實(shí)例屬性name,而類(lèi)的靜態(tài)成員是不影響兼容性的,所以它倆時(shí)兼容的。而類(lèi)Food定義了一個(gè)實(shí)例屬性name,類(lèi)型為number,所以類(lèi)型為Foodf與類(lèi)型為Animala類(lèi)型是不兼容的,不能賦值。

類(lèi)的私有成員和受保護(hù)成員:

類(lèi)的私有成員和受保護(hù)成員會(huì)影響類(lèi)的兼容性。當(dāng)檢查類(lèi)的實(shí)例兼容性時(shí),如果目標(biāo)(要被賦值的那個(gè)值)類(lèi)型(這里實(shí)例類(lèi)型就是創(chuàng)建它的類(lèi))包含一個(gè)私有成員,那么源(用來(lái)賦值的值)類(lèi)型必須包含來(lái)自同一個(gè)類(lèi)的這個(gè)私有成員,這就允許子類(lèi)賦值給父類(lèi):

class?Parent?{
??private?age:?number;
??constructor()?{}
}

class?Children?extends?Parent?{
??constructor()?{
????super();
??}
}

class?Other?{
??private?age:?number;
??constructor()?{}
}

const?children:?Parent?=?new?Children();
const?other:?Parent?=?new?Other();?//?不能將類(lèi)型“Other”分配給類(lèi)型“Parent”。類(lèi)型具有私有屬性“age”的單獨(dú)聲明

當(dāng)指定 other 為 Parent 類(lèi)類(lèi)型,給 other 賦值 Other 創(chuàng)建的實(shí)例的時(shí)候,會(huì)報(bào)錯(cuò)。因?yàn)?nbsp;Parent 的 age 屬性是私有成員,外面是無(wú)法訪(fǎng)問(wèn)到的,所以會(huì)類(lèi)型不兼容。而children的類(lèi)型我們指定為了Parent類(lèi)類(lèi)型,然后給它賦值為Children類(lèi)的實(shí)例,沒(méi)有問(wèn)題,是因?yàn)?code>Children類(lèi)繼承Parent類(lèi),且實(shí)例屬性沒(méi)有差異,Parent類(lèi)有私有屬性age,但是因?yàn)?code>Children類(lèi)繼承了Parent類(lèi),所以可以賦值。

同樣,使用 protected 受保護(hù)修飾符修飾的屬性,也是一樣的:

class?Parent?{
??protected?age:?number;
??constructor()?{}
}

class?Children?extends?Parent?{
??constructor()?{
????super();
??}
}

class?Other?{
??protected?age:?number;
??constructor()?{}
}

const?children:?Parent?=?new?Children();
const?other:?Parent?=?new?Other();?//?不能將類(lèi)型“Other”分配給類(lèi)型“Parent”。屬性“age”受保護(hù),但類(lèi)型“Other”并不是從“Parent”派生的類(lèi)

6. 泛型類(lèi)型兼容性

泛型中包含類(lèi)型參數(shù),這個(gè)類(lèi)型參數(shù)可能是任何類(lèi)型,使用時(shí)類(lèi)型參數(shù)會(huì)被指定為特定的類(lèi)型,而這個(gè)類(lèi)型只影響使用了類(lèi)型參數(shù)的部分:

interface?Data<T>?{}

let?data1:?Data<number>;
let?data2:?Data<string>;
data1?=?data2;?//??

data1 和 data2 都是 Data 接口的實(shí)現(xiàn),但是指定的泛型參數(shù)的類(lèi)型不同,TS 是結(jié)構(gòu)性類(lèi)型系統(tǒng),所以上面將 data2 賦值給 data1 是兼容的,因?yàn)?nbsp;data2 指定了類(lèi)型參數(shù)為 string 類(lèi)型,但是接口里沒(méi)有用到參數(shù) T,所以傳入 string 類(lèi)型還是傳入 number 類(lèi)型并沒(méi)有影響。

再來(lái)看個(gè)例子:

interface?Data<T>?{
??data:?T;
}

let?data1:?Data<number>;
let?data2:?Data<string>;
data1?=?data2;?//?不能將類(lèi)型“Data<string>”分配給類(lèi)型“Data<number>”。不能將類(lèi)型“string”分配給類(lèi)型“number”

現(xiàn)在結(jié)果就不一樣了,賦值時(shí)報(bào)錯(cuò),因?yàn)?nbsp;data1 和 data2 傳入的泛型參數(shù)類(lèi)型不同,生成的結(jié)果結(jié)構(gòu)是不兼容的。

以上就是TypeScript中類(lèi)型兼容性的示例詳解的詳細(xì)內(nèi)容,更多關(guān)于TypeScript類(lèi)型兼容性的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

您可能感興趣的文章:

相關(guān)文章

  • js實(shí)現(xiàn)日期顯示的一些操作(實(shí)例講解)

    js實(shí)現(xiàn)日期顯示的一些操作(實(shí)例講解)

    下面小編就為大家?guī)?lái)一篇js實(shí)現(xiàn)日期顯示的一些操作(實(shí)例講解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • 詳解JavaScript中if語(yǔ)句優(yōu)化和部分語(yǔ)法糖小技巧推薦

    詳解JavaScript中if語(yǔ)句優(yōu)化和部分語(yǔ)法糖小技巧推薦

    在前端日常開(kāi)發(fā)過(guò)程中,if?else判斷語(yǔ)句使用的次數(shù)應(yīng)該是比較頻繁的了,一些較為復(fù)雜的場(chǎng)景,可能會(huì)用到很多判斷,本文給大家介紹JavaScript中if語(yǔ)句優(yōu)化和部分語(yǔ)法糖小技巧,感興趣的朋友一起看看吧
    2022-05-05
  • JS實(shí)現(xiàn)的簡(jiǎn)單標(biāo)簽點(diǎn)擊切換功能示例

    JS實(shí)現(xiàn)的簡(jiǎn)單標(biāo)簽點(diǎn)擊切換功能示例

    這篇文章主要介紹了JS實(shí)現(xiàn)的簡(jiǎn)單標(biāo)簽點(diǎn)擊切換功能,涉及javascript事件響應(yīng)及頁(yè)面元素遍歷、屬性動(dòng)態(tài)變換等相關(guān)操作技巧,需要的朋友可以參考下
    2017-09-09
  • JS獲取Table中td值的方法

    JS獲取Table中td值的方法

    這篇文章主要介紹了JS獲取Table中td值的方法,實(shí)例分析了javascript操作table中td的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-03-03
  • JavaScript包裝對(duì)象使用介紹

    JavaScript包裝對(duì)象使用介紹

    這篇文章主要介紹了JavaScript中包裝對(duì)象的一些知識(shí)點(diǎn),包括內(nèi)置對(duì)象等
    2013-08-08
  • 30個(gè)高逼格代碼的JavaScript高級(jí)單行代碼

    30個(gè)高逼格代碼的JavaScript高級(jí)單行代碼

    這篇文章中列出了一個(gè)系列的 30 個(gè) JavaScript 單行代碼,它們?cè)谑褂?nbsp;vanilla js(≥ ES6)進(jìn)行開(kāi)發(fā)時(shí)非常有用,它們也是使用該語(yǔ)言在最新版本中為我們提供的所有功能來(lái)解決問(wèn)題的優(yōu)雅方式,將它們分為以下5大類(lèi):日期、字符串、數(shù)字、數(shù)組、工具
    2023-08-08
  • JavaScript基于面向?qū)ο髮?shí)現(xiàn)的無(wú)縫滾動(dòng)輪播示例

    JavaScript基于面向?qū)ο髮?shí)現(xiàn)的無(wú)縫滾動(dòng)輪播示例

    這篇文章主要介紹了JavaScript基于面向?qū)ο髮?shí)現(xiàn)的無(wú)縫滾動(dòng)輪播,結(jié)合實(shí)例形式分析了JavaScript面向?qū)ο髮?shí)現(xiàn)的無(wú)縫滾動(dòng)輪播相關(guān)對(duì)象定義、初始化及功能實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2020-01-01
  • 原生js結(jié)合html5制作小飛龍的簡(jiǎn)易跳球

    原生js結(jié)合html5制作小飛龍的簡(jiǎn)易跳球

    這篇文章主要介紹了原生js結(jié)合html5制作小飛龍的簡(jiǎn)易跳球的方法和代碼分享,推薦給大家,有需要的小伙伴可以參考下。
    2015-03-03
  • JScript中使用ADODB.Stream判斷文件編碼的代碼

    JScript中使用ADODB.Stream判斷文件編碼的代碼

    在實(shí)現(xiàn)TextStraem的時(shí)候,找到判斷文件編碼的代碼是VBS的,但是在JScript中是沒(méi)有ASC等函數(shù)的,也不能對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行處理,因此需要通過(guò)一個(gè)特別的方法來(lái)獲取文件開(kāi)關(guān)的編碼標(biāo)識(shí)。
    2008-06-06
  • 驗(yàn)證碼在IE中不刷新而谷歌等瀏覽器正常的解決方案

    驗(yàn)證碼在IE中不刷新而谷歌等瀏覽器正常的解決方案

    在IE中,驗(yàn)證碼不會(huì)刷新而谷歌等其他瀏覽器沒(méi)有問(wèn)題,解決方案就是在驗(yàn)證碼的切換地址后面加一個(gè)隨機(jī)的參數(shù)
    2014-03-03

最新評(píng)論