最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

TypeScript開(kāi)發(fā)小狀況記錄之選且只選一個(gè)

 更新時(shí)間:2022年10月05日 08:44:03   作者:Rio_Kwok  
在開(kāi)發(fā)中需要定義一個(gè)對(duì)象的類型,此類型必須包含某n個(gè)字段中的其中一種,這篇文章主要給大家介紹了關(guān)于TypeScript開(kāi)發(fā)小狀況記錄之選且只選一個(gè)的相關(guān)資料,需要的朋友可以參考下

前言

在項(xiàng)目?jī)?nèi),使用TypeScript的過(guò)程中遇到了一些狀況、報(bào)錯(cuò)或棘手的情況,決定開(kāi)一個(gè)系列記錄遇到的問(wèn)題和我的解決方法。

背景

在項(xiàng)目開(kāi)發(fā)中,很多時(shí)候會(huì)遇到一種場(chǎng)景,需要定義一個(gè)對(duì)象的類型,此類型必須包含某n個(gè)字段中的其中一種。

例如,我要定義一個(gè)工程師(Engineer)的對(duì)象,里面包括姓名(name),性別(gender),年齡(age)和一門(mén)編程語(yǔ)言(java/cpp/go/js四選一)的評(píng)價(jià)。

顯然,前三個(gè)字段都是很簡(jiǎn)單的,但是第四個(gè)就有點(diǎn)麻煩了。首先,第四個(gè)字段的key是可以不一樣(甚至value也有可能不同),其次字段只能從給定的里面4選1。

初步方案

一開(kāi)始是考慮使用可選或聯(lián)合類型,但是發(fā)現(xiàn)沒(méi)有辦法進(jìn)行4選1的限制,對(duì)于沒(méi)有編程語(yǔ)言字段,或者多個(gè)編程語(yǔ)言字段的情況并沒(méi)有很好的限制。最后只能使用泛型,再使用時(shí)進(jìn)行顯式的聲明。

于是,類型定義如下:

interface ICodingLangRating {
    java: string
    cpp: string
    go: string
    js: string
}

type Engineer<K extends keyof ICodingLangRating> = {
    name: string
    gender: 'male' | 'female'
    age: number
} & Pick<ICodingLangRating, K>

對(duì)該聲明的校驗(yàn)代碼如下:

// 正確
const candidate: Engineer<'java'> = {
    name: 'Jack',
    gender: 'male',
    age: 22,
    java: 'fabulous'
}

// 錯(cuò)誤,聲明了java,但是卻同時(shí)定義了java和go字段
const candidate_1: Engineer<'java'> = {
    name: 'Jack',
    gender: 'male',
    age: 22,
    java: 'fabulous',
    go: 'not bad'
}

// 錯(cuò)誤,聲明了java,但是類型不正確
const candidate_2: Engineer<'java'> = {
    name: 'Jack',
    gender: 'male',
    age: 22,
    java: 666
}

// 錯(cuò)誤,聲明了java,但是卻定義了go字段
const candidate_3: Engineer<'java'> = {
    name: 'Jack',
    gender: 'male',
    age: 22,
    go: 'not bad'
}

// 錯(cuò)誤,聲明了java,但是卻同時(shí)定義了cpp和go字段
const candidate_4: Engineer<'java'> = {
    name: 'Jack',
    gender: 'male',
    age: 22,
    cpp: 'unknown',
    go: 'not bad'
}

// 錯(cuò)誤,聲明了java,但是卻沒(méi)有定義java字段
const candidate_5: Engineer<'java'> = {
    name: 'Jack',
    gender: 'male',
    age: 22
}

// 錯(cuò)誤,聲明了ICodingLangRating中不存在的python
const candidate_6: Engineer<'python'> = {
    name: 'Jack',
    gender: 'male',
    age: 22,
    python: 'just so so'
}

從校驗(yàn)代碼可以看出,針對(duì)各種不符合期望的情況:

  • 聲明a,卻定義a和b
  • 聲明a,但定義a的類型不正確
  • 聲明a,卻定義b
  • 聲明a,卻定義b和c
  • 聲明a,卻沒(méi)有定義a
  • 聲明不合法的f

都能做出正確的限制,確保在業(yè)務(wù)場(chǎng)景的代碼中,有且只有一個(gè)合法范圍的字段。

但是,轉(zhuǎn)折來(lái)了!

在后來(lái)的使用中,我們發(fā)現(xiàn),其實(shí)這個(gè)解決方案只是一個(gè)弱限制,如果在泛型的顯式聲明中,傳入聯(lián)合類型的話,那還是可以繞過(guò)有且只有一個(gè)編程語(yǔ)言字段的限制。

// 正確,聲明了java和go,并同時(shí)定義了java和go字段
const candidate_1: Engineer<'java' | 'go'> = {
    name: 'Jack',
    gender: 'male',
    age: 22,
    java: 'fabulous',
    go: 'not bad'
}

難道就真的沒(méi)有辦法做到只能選擇一個(gè)的限制么?

終極方案

根據(jù)上面的嘗試,目前我們還缺少的是如何阻止同時(shí)有2個(gè)或以上的合法字段出現(xiàn)。最笨的方式就是為每一個(gè)語(yǔ)言都定義一個(gè)類似{ langName: string }這樣的類型然后通過(guò)extends或者聯(lián)合類型使用,但是顯然這樣就沒(méi)有辦法做到在其它情況通用。

而通過(guò)官方現(xiàn)成的工具類型,由于都是支持字面量和聯(lián)合類型,沒(méi)有辦法篩選出只包含一個(gè)字段的類型。就在這時(shí),我想到,是不是可以定義出一個(gè)類型,包含全部字段,但是只有一個(gè)字段是正確有意義,其他字段都是無(wú)意義的呢。

最終,我就構(gòu)造出下面這個(gè)PickOne工具類型:

type PickOne<T> = {
    [K in keyof T]: Record<K, T[K]> & Partial<Record<Exclude<keyof T, K>, undefined>>
}[keyof T]

測(cè)試代碼如下:

type OneLang = PickOne<ICodingLangRating>

// 正確
const lang: OneLang = {
    java: 'good'
}

// 錯(cuò)誤
const lang2: OneLang = {
    python: 'unknown'
}

// 錯(cuò)誤
const lang3: OneLang = {
    java: 'good',
    go: 'good'
}

// 錯(cuò)誤
const lang4: OneLang = {
    java: 123
}

最后,類型定義代碼如下:

interface ICodingLangRating {
    java: string
    cpp: string
    go: string
    js: string
}

type Engineer = {
    name: string
    gender: 'male' | 'female'
    age: number
} & PickOne<ICodingLangRating>

使用了這個(gè)PickOne工具類型,我不需要在使用的時(shí)候顯式的指定編程語(yǔ)言,甚至還能在其它類似的場(chǎng)景使用。

總結(jié)

到此這篇關(guān)于TypeScript開(kāi)發(fā)小狀況記錄之選且只選一個(gè)的文章就介紹到這了,更多相關(guān)TypeScript選且只選一個(gè)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 揭秘JavaScript Reduce的用法

    揭秘JavaScript Reduce的用法

    作為高級(jí)前端切圖仔,我們經(jīng)常遇到需要處理、聚合或轉(zhuǎn)換數(shù)據(jù)的場(chǎng)景,JavaScript 的reduce()方法是一個(gè)強(qiáng)大的工具,它允許我們有效地迭代數(shù)組并累積單個(gè)值,從而簡(jiǎn)化了這些任務(wù),本文將給大家揭秘JavaScript Reduce方法,需要的朋友可以參考下
    2023-09-09
  • javascript隱藏顯示div的兩種方式實(shí)例

    javascript隱藏顯示div的兩種方式實(shí)例

    這篇文章主要給大家介紹了關(guān)于javascript隱藏顯示div的兩種方式,實(shí)現(xiàn)的代碼很簡(jiǎn)單,點(diǎn)擊時(shí)先判斷div是否是顯示,如果div是顯示就把div設(shè)置為隱藏,否則就變?yōu)轱@示,需要的朋友可以參考下
    2022-09-09
  • js圖片輪播特效代碼分享

    js圖片輪播特效代碼分享

    這篇文章主要介紹了js圖片輪播特效,圖片切換效果特別適合做產(chǎn)品演示,感興趣的小伙伴可以參考下
    2015-09-09
  • ymyang 繪圖 實(shí)例代碼

    ymyang 繪圖 實(shí)例代碼

    非常不錯(cuò)的ymyang 繪圖效果代碼。
    2009-04-04
  • JS兼容所有瀏覽器的DOMContentLoaded事件

    JS兼容所有瀏覽器的DOMContentLoaded事件

    這篇文章主要介紹了JS兼容所有瀏覽器的DOMContentLoaded事件的相關(guān)資料,標(biāo)準(zhǔn)瀏覽器中,使用DOMContentLoaded事件即可實(shí)現(xiàn)我們的要求,注冊(cè)事件處理函數(shù)也極為簡(jiǎn)單,感興趣的朋友一起學(xué)習(xí)吧
    2018-01-01
  • JavaScript canvas實(shí)現(xiàn)刮刮樂(lè)案例

    JavaScript canvas實(shí)現(xiàn)刮刮樂(lè)案例

    這篇文章主要為大家詳細(xì)介紹了JavaScript canvas實(shí)現(xiàn)刮刮樂(lè)案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • sso跨域?qū)慶ookie的一段js腳本(推薦)

    sso跨域?qū)慶ookie的一段js腳本(推薦)

    下面小編就為大家?guī)?lái)一篇sso跨域?qū)慶ookie的一段js腳本(推薦)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-05-05
  • 全面解析JavaScript中apply和call以及bind(推薦)

    全面解析JavaScript中apply和call以及bind(推薦)

    在javascript中apply、call和bind是三兄弟,很好的搭檔,下面小編給大家全面解析JavaScript中apply和call以及bind的相關(guān)知識(shí),感興趣的朋友一起學(xué)習(xí)吧
    2016-06-06
  • javascript 開(kāi)發(fā)之百度地圖使用到的js函數(shù)整理

    javascript 開(kāi)發(fā)之百度地圖使用到的js函數(shù)整理

    這篇文章主要介紹了javascript 開(kāi)發(fā)之百度地圖使用到的js函數(shù)整理的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • 如何在微信小程序?qū)崿F(xiàn)一個(gè)幸運(yùn)轉(zhuǎn)盤(pán)小游戲

    如何在微信小程序?qū)崿F(xiàn)一個(gè)幸運(yùn)轉(zhuǎn)盤(pán)小游戲

    這篇文章主要給大家介紹了關(guān)于如何在微信小程序?qū)崿F(xiàn)一個(gè)幸運(yùn)轉(zhuǎn)盤(pán)小游戲的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04

最新評(píng)論

如东县| 建始县| 怀仁县| 宁远县| 科技| 宁阳县| 昔阳县| 靖江市| 巴塘县| 祁连县| 长白| 五原县| 新乐市| 宜兰县| 长阳| 曲麻莱县| 高碑店市| 曲沃县| 滦平县| 鲜城| 乐山市| 郸城县| 沈阳市| 文安县| 瑞丽市| 武汉市| 苏州市| 沙雅县| 沈丘县| 昌黎县| 罗山县| 万荣县| 湘潭市| 平山县| 夏津县| 阿克陶县| 衡南县| 新营市| 肥西县| 沙坪坝区| 赣榆县|