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

詳解Typescript中奇怪的賦值操作

 更新時(shí)間:2024年02月19日 15:45:09   作者:不如吃茶去  
這篇文章主要來和大家討論一下typescript中一些奇怪的賦值語句,探索其背后原因,更深入的了解typescript作為一個(gè)結(jié)構(gòu)化系統(tǒng)的特性,感興趣的可以了解下

前言

本文主要討論在typescript中一些奇怪的賦值語句,探索其背后原因,更深入的了解typescript作為一個(gè)結(jié)構(gòu)化系統(tǒng)的特性。

我們先看這樣一個(gè)例子:

// 定義一個(gè)Cat類
class Cat {
  name!: string
  age!: number
?
  constructor(name: string, age: number) {
    this.name = name
    this.age = age
  }
}
// 定義一個(gè)Dog接口類型
interface Dog {
  name: string
  age: number
}
?
let dog: Dog = {
  name: 'wuyue',
  age: 3
}
?
let cat: Cat
cat = new Cat('qiqi', 2)
cat = dog // is ok 
dog = cat // is ok 
cat = { name: 'jack', age: 12 } // is ok
  • 在上面的例子中,我們定義了一個(gè)Cat類,一個(gè)Dog接口類型, Cat類的實(shí)例對(duì)象與Dog類型的變量相互賦值,可以通過Typescript的類型檢查,而將{ name: 'jack', age: 12 }分配給一個(gè)Cat類型的變量也是可以的。
  • 這是結(jié)構(gòu)化類型系統(tǒng)的特性,Typescript就采用了這種結(jié)構(gòu)類型。結(jié)構(gòu)化類型系統(tǒng)的思想在于,名稱不重要,重要的是它們是否具有類型的相同成員,如果是則是兼容的。 結(jié)構(gòu)化類型系統(tǒng)也叫鴨子類型, 如果你看到一只鳥走起來像鴨子,游泳像鴨子,叫得也像鴨子,那么這只鳥就是鴨子。
  • 上個(gè)例子中cat變量,dog變量,以及{ name: 'jack', age: 12 } 字面量他們都具有相同的結(jié)構(gòu),所以Typescript在類型檢查時(shí)認(rèn)為他們之間的賦值操作是合法的。

我們?cè)賮砜戳硪粋€(gè)例子

// 定義一個(gè)Cat類
class Cat {
  name!: string
  age!: number
?
  constructor(name: string, age: number) {
    this.name = name
    this.age = age
  }
}
// 定義一個(gè)Dog接口類型
interface Dog {
  name: string
  age: number
}
let dog: Dog = {
  name: 'wuyue',
  age: 3
}
?
function getCat(cat: Cat) {}
?
getCat(new Cat('cc', 2)) // ok
getCat(dog) // ok
getCat({ name: 'jack', age: 12 }) // ok
const obj = { name: 'jack', age: 12, sex: 1 } // ok
getCat(obj) // ? ok

在這個(gè)例子中,我們定義的Cat類和Dog接口類型和上面的例子一致,緊接著我們定義了一個(gè)getCat的函數(shù),接受一個(gè)Cat類型的形參。

根據(jù)上一個(gè)例子中我們學(xué)到的結(jié)構(gòu)化類型系統(tǒng)的知識(shí),可以很快的判斷出來 new Cat('cc', 2)、dog{ name: 'jack', age: 12 } 都可以分配給Cat類型的變量,那么最后一個(gè)可以嗎? 我們?cè)?typescript Playground中測(cè)試發(fā)現(xiàn)是可以的,typescript對(duì)上面的代碼都通過了類型檢查,但是你可能還有困惑,obj明顯多了一個(gè)sex屬性,而sex屬性在Cat類型中并不存在,Typescript為什么也對(duì)其通過了類型檢查?先放下這個(gè)疑問,我們?cè)诳催@么一行代碼

getCat({ name: 'jack', age: 12, sex: 1 }) 

這行代碼竟然報(bào)錯(cuò)了,事情變得更加奇怪了。

再來看一個(gè)例子:

是不是很奇怪,同樣的值,直接賦值/傳參會(huì)報(bào)錯(cuò),如果先定義一個(gè)變量然后將這個(gè)變量進(jìn)行賦值/傳參就不會(huì)報(bào)錯(cuò)。

通過查閱各種官方資料發(fā)現(xiàn)這么一個(gè)結(jié)論: 在typescript類型系統(tǒng)中,對(duì)對(duì)象進(jìn)行類型檢查時(shí)定義的方式會(huì)對(duì)結(jié)果產(chǎn)生影響,在創(chuàng)建一個(gè)對(duì)象字面量并直接分配給具有某個(gè)類型的變量時(shí),typescript會(huì)最嚴(yán)謹(jǐn)?shù)尿?yàn)證對(duì)象, 進(jìn)行嚴(yán)格的屬性檢查(ECP),而當(dāng)將對(duì)象變量分配給另一個(gè)變量,對(duì)這個(gè)變量進(jìn)行類型檢查時(shí),typescript會(huì)進(jìn)行兼容性判斷,如果兼容則通過檢查,如果不兼容則報(bào)錯(cuò)。

而這個(gè)兼容性判斷是如何判斷的呢? 請(qǐng)記住下面這句話:

假如x要分配給y,在TypeScript中,X需要更具體,即X要有和Y相同的屬性或者更多。 可分配性指的就是兼容性。

如: let v = { name: 'john'; age: 20 } 兼容{ name: string }, 類型兼容,通過檢查。let v = {foo: 1, bar: 2} 兼容{foo: number} , 類型兼容,通過檢查。而這個(gè)問題可以被看成是類型加寬。

對(duì)于上面的現(xiàn)象,有好處也有壞處,對(duì)此有人提出來typescript新加入一個(gè)精確類型的語法,引起了激烈的討論:可以看下面這個(gè)鏈接。 #12936

結(jié)尾

在網(wǎng)上大多數(shù)的案例中,總是會(huì)出現(xiàn)這樣的例子:

interface Person {
  name: string
  age: number
}

let p: Person = {
  name: 'jack',
  age: 12,
}

我們似乎認(rèn)為p變量一定要精確的滿足于Person的定義,如果多加了屬性那么就會(huì)報(bào)錯(cuò),這是typescript的基石,ts就應(yīng)該做這樣的事,其實(shí)不然,typescript作為一個(gè)結(jié)構(gòu)化系統(tǒng),多加了屬性并不會(huì)報(bào)錯(cuò), “多加了屬性那么就會(huì)報(bào)錯(cuò)” 的功能其實(shí)是在typescript中是一種linter校驗(yàn)的功能,而且它僅適用于對(duì)象字面量。所以有時(shí)候我們也會(huì)說Typescript是Javascript一個(gè)超級(jí)強(qiáng)大的linter工具

到此這篇關(guān)于詳解Typescript中奇怪的賦值操作的文章就介紹到這了,更多相關(guān)Typescript賦值操作內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論