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

TypeScript中條件類(lèi)型精讀與實(shí)踐記錄

 更新時(shí)間:2021年10月05日 08:25:10   作者:牧云云  
這篇文章主要給大家介紹了關(guān)于TypeScript中條件類(lèi)型精讀與實(shí)踐的相關(guān)資料,,條件類(lèi)型就是在初始狀態(tài)并不直接確定具體類(lèi)型,而是通過(guò)一定的類(lèi)型運(yùn)算得到最終的變量類(lèi)型,需要的朋友可以參考下

在大多數(shù)程序中,我們必須根據(jù)輸入做出決策。TypeScript 也不例外,使用條件類(lèi)型可以描述輸入類(lèi)型與輸出類(lèi)型之間的關(guān)系。

用于條件判斷時(shí)的 extends

當(dāng) extends 用于表示條件判斷時(shí),可以總結(jié)出以下規(guī)律

若位于 extends 兩側(cè)的類(lèi)型相同,則 extends 在語(yǔ)義上可理解為 ===,可以參考如下例子:

type result1 = 'a' extends 'abc' ? true : false // false
type result2 = 123 extends 1 ? true : false     // false

若位于 extends 右側(cè)的類(lèi)型包含位于 extends 左側(cè)的類(lèi)型(即狹窄類(lèi)型 extends 寬泛類(lèi)型)時(shí),結(jié)果為 true,反之為 false。可以參考如下例子:

type result3 = string extends string | number ? true : false // true

當(dāng) extends 作用于對(duì)象時(shí),若在對(duì)象中指定的 key 越多,則其類(lèi)型定義的范圍越狹窄??梢詤⒖既缦吕?

type result4 = { a: true, b: false } extends { a: true } ? true : false // true

在泛型類(lèi)型中使用條件類(lèi)型

考慮如下 Demo 類(lèi)型定義:

type Demo<T, U> = T extends U ? never : T

結(jié)合用于條件判斷時(shí)的 extends,可知 'a' | 'b' | 'c' extends 'a' 是 false, 因此 Demo<'a' | 'b' | 'c', 'a'> 結(jié)果是 'a' | 'b' | 'c' 么?
查閱官網(wǎng),其中有提到:

When conditional types act on a generic type, they become distributive when given a union type.

即當(dāng)條件類(lèi)型作用于泛型類(lèi)型時(shí),聯(lián)合類(lèi)型會(huì)被拆分使用。即 Demo<'a' | 'b' | 'c', 'a'> 會(huì)被拆分為 'a' extends 'a'、'b' extends 'a'、'c' extends 'a'。用偽代碼表示類(lèi)似于:

function Demo(T, U) {
  return T.map(val => {
    if (val !== U) return val
    return 'never'
  })
}

Demo(['a', 'b', 'c'], 'a') // ['never', 'b', 'c']

此外根據(jù) never 類(lèi)型的定義 —— never 類(lèi)型可分配給每種類(lèi)型,但是沒(méi)有類(lèi)型可以分配給 never(除了 never 本身)。即 never | 'b' | 'c' 等價(jià)于 'b' | 'c'。

因此 Demo<'a' | 'b' | 'c', 'a'> 的結(jié)果并不是 'a' | 'b' | 'c' 而是 'b' | 'c'。

工具類(lèi)型

心細(xì)的讀者可能已經(jīng)發(fā)現(xiàn)了 Demo 類(lèi)型的聲明過(guò)程其實(shí)就是 TypeScript 官方提供的工具類(lèi)型中 Exclude<Type, ExcludedUnion> 的實(shí)現(xiàn)原理,其用于將聯(lián)合類(lèi)型 ExcludedUnion 排除在 Type 類(lèi)型之外。

type T = Demo<'a' | 'b' | 'c', 'a'> // T: 'b' | 'c'

基于 Demo 類(lèi)型定義,進(jìn)一步地還可以實(shí)現(xiàn)官方工具類(lèi)型中的 Omit<Type, Keys>,其用于移除對(duì)象 Type
中滿足 keys 類(lèi)型的屬性值。

type Omit<Type, Keys> = {
  [P in Demo<keyof Type, Keys>]: Type<P>
}

interface Todo {
  title: string;
  description: string;
  completed: boolean;
}

type T = Omit<Todo, 'description'> // T: { title: string; completed: boolean }

逃離艙

如果想讓 Demo<'a' | 'b' | 'c', 'a'> 的結(jié)果為 'a' | 'b' | 'c' 是否可以實(shí)現(xiàn)呢? 根據(jù)官網(wǎng)描述:

Typically, distributivity is the desired behavior. To avoid that behavior, you can surround each side of the extends keyword with square brackets.

如果不想遍歷泛型中的每一個(gè)類(lèi)型,可以用方括號(hào)將泛型給括起來(lái)以表示使用該泛型的整體部分。
type Demo<T, U> = [T] extends [U] ? never : T

type Demo<T, U> = [T] extends [U] ? never : T

// result 此時(shí)類(lèi)型為 'a' | 'b' | 'c'
type result = Demo<'a' | 'b' | 'c', 'a'>

在箭頭函數(shù)中使用條件類(lèi)型

在箭頭函數(shù)中使用三元表達(dá)式時(shí),從左向右的閱讀習(xí)慣導(dǎo)致函數(shù)內(nèi)容區(qū)若不加括號(hào)則會(huì)讓使用方感到困惑。比如下方代碼中 x 是函數(shù)類(lèi)型還是布爾類(lèi)型呢?

// The intent is not clear.
var x = a => 1 ? true : false

在 eslint 規(guī)則 no-confusing-arrow 中,推薦如下寫(xiě)法:

var x = a => (1 ? true : false)

在 TypeScript 的類(lèi)型定義中,若在箭頭函數(shù)中使用 extends 也是同理,由于從左向右的閱讀習(xí)慣,也會(huì)導(dǎo)致閱讀者對(duì)類(lèi)型代碼的執(zhí)行順序感到困惑。

type Curry<P extends any[], R> =
  (arg: Head<P>) => HasTail<P> extends true ? Curry<Tail<P>, R> : R

因此在箭頭函數(shù)中使用 extends 建議加上括號(hào),對(duì)于進(jìn)行 code review 有很大的幫助。

type Curry<P extends any[], R> =
  (arg: Head<P>) => (HasTail<P> extends true ? Curry<Tail<P>, R> : R)

結(jié)合類(lèi)型推導(dǎo)使用條件類(lèi)型

在 TypeScript 中,一般會(huì)結(jié)合 extends 來(lái)使用類(lèi)型推導(dǎo) infer 語(yǔ)法。使用它可以實(shí)現(xiàn)自動(dòng)推導(dǎo)類(lèi)型的目的。比如用其來(lái)實(shí)現(xiàn)工具類(lèi)型 ReturnType<Type> ,該工具類(lèi)型用于返回函數(shù) Type 的返回類(lèi)型。
type ReturnType<T extends Function> = T extends (...args: any) => infer U ? U : never

type ReturnType<T extends Function> = T extends (...args: any) => infer U ? U : never

MyReturnType<() => string>          // string
MyReturnType<() => Promise<boolean> // Promise<boolean>

結(jié)合 extends 與類(lèi)型推導(dǎo)還可以實(shí)現(xiàn)與數(shù)組相關(guān)的 Pop<T>、Shift<T>、Reverse<T> 工具類(lèi)型。

Pop<T>:

type Pop<T extends any[]> = T extends [...infer ExceptLast, any] ? ExceptLast : never

type T = Pop<[3, 2, 1]> // T: [3, 2]

Shift<T>:

type Shift<T extends any[]> = T extends [infer _, ...infer O] ? O : never

type T = Shift<[3, 2, 1]> // T: [2, 1]

Reverse<T>

type Reverse<T> = T extends [infer F, ...infer Others]
  ? [...Reverse<Others>, F]
  : []

type T = Reverse<['a', 'b']> // T: ['b', 'a']

使用條件類(lèi)型來(lái)判斷兩個(gè)類(lèi)型完全相等

我們也可以使用條件類(lèi)型來(lái)判斷 A、B 兩個(gè)類(lèi)型是否完全相等。當(dāng)前社區(qū)上主要有兩種方案:

方案一: 參考 issue。

export type Equal1<T, S> =
  [T] extends [S] ? (
    [S] extends [T] ? true : false
  ) : false

目前該方案的唯一缺點(diǎn)是會(huì)將 any 類(lèi)型與其它任何類(lèi)型判為相等。

type T = Equal1<{x:any}, {x:number}> // T: true

方案二: 參考 issue。

export type Equal2<X, Y> =
  (<T>() => T extends X ? 1 : 2) extends
  (<U>() => U extends Y ? 1 : 2) ? true : false

目前該方案的唯一缺點(diǎn)是在對(duì)交叉類(lèi)型的處理上有一點(diǎn)瑕疵。

type T = Equal2<{x:1} & {y:2}, {x:1, y:2}> // false

以上兩種判斷類(lèi)型相等的方法見(jiàn)仁見(jiàn)智,筆者在此拋磚引玉。

總結(jié)

到此這篇關(guān)于TypeScript中條件類(lèi)型精讀與實(shí)踐的文章就介紹到這了,更多相關(guān)TypeScript條件類(lèi)型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于Bootstrap實(shí)現(xiàn)的下拉菜單手機(jī)端不能選擇菜單項(xiàng)的原因附解決辦法

    基于Bootstrap實(shí)現(xiàn)的下拉菜單手機(jī)端不能選擇菜單項(xiàng)的原因附解決辦法

    小編使用bootstrap做的下拉菜單在電腦瀏覽器中可以正常使用,在手機(jī)瀏覽器中能彈出下拉列表卻不能選擇列表中的菜單項(xiàng),怎么回事,如何解決呢?下面小編給大家分享下具體原因及解決辦法,一起看下吧
    2016-07-07
  • JavaScript中DOM尺寸測(cè)量與節(jié)流技巧總結(jié)

    JavaScript中DOM尺寸測(cè)量與節(jié)流技巧總結(jié)

    在網(wǎng)頁(yè)開(kāi)發(fā)中,合理獲取DOM元素尺寸及使用節(jié)流技術(shù)對(duì)高頻事件進(jìn)行優(yōu)化,是確保頁(yè)面流暢運(yùn)行的關(guān)鍵,通過(guò)JavaScript可以方便地獲取元素寬高,并應(yīng)用節(jié)流(Throttle)與防抖(Debounce)技術(shù)處理如滾動(dòng)或窗口調(diào)整等高頻事件,有效減少性能消耗,需要的朋友可以參考下
    2024-11-11
  • JS實(shí)現(xiàn)彈性漂浮效果的廣告代碼

    JS實(shí)現(xiàn)彈性漂浮效果的廣告代碼

    這篇文章主要介紹了JS實(shí)現(xiàn)彈性漂浮效果的廣告代碼,涉及javascript動(dòng)態(tài)操作圖片彈性運(yùn)動(dòng)效果的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-09-09
  • 基于layui的下拉列表的數(shù)據(jù)回顯方法

    基于layui的下拉列表的數(shù)據(jù)回顯方法

    今天小編就為大家分享一篇基于layui的下拉列表的數(shù)據(jù)回顯方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-09-09
  • JavaWeb表單及時(shí)驗(yàn)證功能在輸入后立即驗(yàn)證(含用戶類(lèi)型,性別,愛(ài)好...的驗(yàn)證)

    JavaWeb表單及時(shí)驗(yàn)證功能在輸入后立即驗(yàn)證(含用戶類(lèi)型,性別,愛(ài)好...的驗(yàn)證)

    最近做項(xiàng)目遇到表單在輸入后立即驗(yàn)證,而不是提交后再驗(yàn)證,在網(wǎng)上找了下資料,沒(méi)有合適的,于是我自己動(dòng)手寫(xiě)了一個(gè),分享到腳本之家平臺(tái),供大家參考
    2017-06-06
  • 兼容IE與Firefox的js 復(fù)制代碼

    兼容IE與Firefox的js 復(fù)制代碼

    這是一段點(diǎn)擊復(fù)制的代碼,現(xiàn)在我的頁(yè)面里不僅有1個(gè)鏈接需要用到這段代碼。請(qǐng)哪位好心人指教一下應(yīng)該怎么用ID對(duì)應(yīng)的方式來(lái)改寫(xiě)這段js,使它實(shí)現(xiàn)一個(gè)點(diǎn)擊復(fù)制對(duì)應(yīng)1個(gè)相應(yīng)內(nèi)容
    2009-12-12
  • javascript時(shí)間排序算法實(shí)現(xiàn)活動(dòng)秒殺倒計(jì)時(shí)效果

    javascript時(shí)間排序算法實(shí)現(xiàn)活動(dòng)秒殺倒計(jì)時(shí)效果

    這篇文章主要介紹了javascript時(shí)間排序算法實(shí)現(xiàn)活動(dòng)秒殺倒計(jì)時(shí)效果,即一個(gè)頁(yè)面多個(gè)倒計(jì)時(shí)排序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-03-03
  • 淺談webpack組織模塊的原理

    淺談webpack組織模塊的原理

    這篇文章主要介紹了淺談webpack組織模塊的原理,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • JavaScript性能優(yōu)化之減少DOM操作全方位攻略指南

    JavaScript性能優(yōu)化之減少DOM操作全方位攻略指南

    DOM操作是Web開(kāi)發(fā)中最耗性能的操作之一,頻繁的DOM訪問(wèn)和修改會(huì)導(dǎo)致瀏覽器不斷重繪和回流,嚴(yán)重影響頁(yè)面性能,下面我們就來(lái)看看JavaScript減少DOM操作的具體方法吧
    2025-12-12
  • 前端列表狀態(tài)無(wú)感知?jiǎng)討B(tài)刷新的實(shí)現(xiàn)方案

    前端列表狀態(tài)無(wú)感知?jiǎng)討B(tài)刷新的實(shí)現(xiàn)方案

    這篇文章主要為大家詳細(xì)介紹了幾種常見(jiàn)的前端列表狀態(tài)無(wú)感知?jiǎng)討B(tài)刷新方案,本文分析了它們的原理、優(yōu)缺點(diǎn)及適用場(chǎng)景,希望可以幫助開(kāi)發(fā)者根據(jù)實(shí)際需求做出選擇
    2025-08-08

最新評(píng)論

阳山县| 汉源县| 汉中市| 丰宁| 翁源县| 泗水县| 巢湖市| 寿光市| 黄大仙区| 新邵县| 温宿县| 赤壁市| 辛集市| 汉寿县| 枣阳市| 阿克陶县| 北海市| 宜阳县| 紫云| 镇原县| 平凉市| 玉环县| 三亚市| 本溪| 华蓥市| 手游| 松溪县| 南召县| 五指山市| 凤城市| 红原县| 华安县| 淮北市| 铜川市| 开江县| 沽源县| 湖北省| 漳平市| 达孜县| 莱芜市| 壤塘县|