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

詳解Typescript中奇怪的賦值操作

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

前言

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

我們先看這樣一個例子:

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

我們再來看另一個例子

// 定義一個Cat類
class Cat {
  name!: string
  age!: number
?
  constructor(name: string, age: number) {
    this.name = name
    this.age = age
  }
}
// 定義一個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

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

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

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

這行代碼竟然報錯了,事情變得更加奇怪了。

再來看一個例子:

是不是很奇怪,同樣的值,直接賦值/傳參會報錯,如果先定義一個變量然后將這個變量進行賦值/傳參就不會報錯。

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

而這個兼容性判斷是如何判斷的呢? 請記住下面這句話:

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

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

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

結尾

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

interface Person {
  name: string
  age: number
}

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

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

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

相關文章

最新評論