typescript type 分配條件類型示例詳解
引言
接上文type challenge(easy部分)關(guān)于分配條件類型,官方文檔描述地址。
之前看的時候沒真正理解,關(guān)于聯(lián)合類型的分配條件,官方文檔其實也沒有講得很明白,和翻譯無關(guān),英文文檔一樣很模糊,這些天做type challenge,發(fā)現(xiàn)有些題做出來的結(jié)果和預期不太一致,所以重新梳理這塊內(nèi)容。
先說結(jié)論
聯(lián)合類型什么時候會分配,必須符合4個條件(后面直接用條件1、條件2等代指下面條件):
首先,只分配extends前的內(nèi)容
- 無論這個extends是不是子斷言語句中的
- 例如
type Test<T> = 'b' extends 'b' ? (T extends 'b' ? true: false) : false;
, 其中的T extends 'b'
在子語句中,但事實上依舊是有效的
分配的內(nèi)容未做任何處理
type Test<T> = keyof T extends null ? never: false;
,T
被keyof
操作符處理了,因此不會分配- 官方文檔中,提到避免分配的方法
type ToArrayNonDist<Type> = [Type] extends [any] ? Type[] : never;
,能規(guī)避分配也是這個道理
分配內(nèi)容必須作為參數(shù)傳入
傳入時是聯(lián)合類型
題目解析
驗證條件
條件1
type Test<T> = 'b' extends 'b' ? (T extends 'b' ? true: false) : false; Test<'a'| 'b'> // boolean
可見在子條件中的extends
也符合自動分配,否則'a'|'b' extends 'b'
會返回false
,而不是true|false
條件2
發(fā)現(xiàn)這個問題是在DeepReadonly,題目地址
這一題一看看過去,直接寫出如下:
type DeepReadonly<T> = keyof T extends never ? T : {readonly [k in keyof T]: DeepReadonly<T[k]>};
但是發(fā)現(xiàn)對于測試用例X2
不生效
type X2 = { a: string } | { b: number }; DeepReadonly<X2> // { a: string } | { b: number }
仔細看,雖然X2是聯(lián)合類型,但keyof T extends never
顯然不符合前面說的條件2,因此不會自動分配,而keyof ({ a: string } | { b: number })
值為never
。因此該題正確寫法如下:
type DeepReadonly<T> = { readonly [P in keyof T]: keyof T[P] extends never ? T[P] : DeepReadonly<T[P]>; };
條件3
顯然,普通使用extands
不會觸發(fā)自動分配
type Test = 'a'|'b' extends 'a' ? true: false; // false
那么,假設(shè)傳入的參數(shù)是聯(lián)合類型,extends
前的對象也是聯(lián)合類型呢?
type Test<T> = 'b' extends 'b' ? (keyof T extends 'b' ? true: false) : false; type Result = Test<{a:1,b:string}|{a:2,b:number}> // false
這里,參數(shù)T
是聯(lián)合類型,但extends
前進行了keyof
處理,但keyof {a:1,b:string}|{a:2,b:number}
結(jié)果為'a'|'b'
,依然是聯(lián)合類型,若這里進行了自動分配,結(jié)果應是boolean
而非false
。
根據(jù)結(jié)果來看,這里并未進行分配,這個例子同時違背了條件2和條件3
條件4
type Test<T> = 'a'|'b' extends 'b' ? T: false; Test<5> // false
條件4顯而易見,官方文檔上已經(jīng)說的很明確了。
不注意優(yōu)先級導致的錯誤
在測試分配條件類型的規(guī)律時,曾因為一條用例卡了半天,用例如下:
type A = keyof null|undefined; // undefined type UndefinedExtendsNull = undefined extends null ? true: false; //false type Test<T> = keyof T extends null ? true: false; Test<null|undefined>; // true ?。。?!
此時已經(jīng)知道了,keyof T
會避免自動分配,因此對于Test<null|undefined>
,可以寫成
keyof null|undefined extends null ? true : false; // 這里有個坑...
而keyof null|undefined
結(jié)果是undefined
,但是
type UndefinedExtendsNull = undefined extends null ? true: false; //false
結(jié)果是false
,同樣的式子,結(jié)果不一樣,一開始我以為是分配規(guī)律的理解有問題,但即使分配了,結(jié)果也應該是true|false
,也就是boolean
,而不是true
。
后來發(fā)現(xiàn),type
是有優(yōu)先級的,且keyof
優(yōu)先級高于|
.
按理說keyof null|undefined
結(jié)果應該是never
,之所以會顯示結(jié)果是undefined
,是因為優(yōu)先級運算:
keyof null|undefined -> (keyof null)|undefined -> never|undefined -> undefined
在實際寫類型的時候,要重點注意優(yōu)先級問題
以上就是typescript type 分配條件類型示例詳解的詳細內(nèi)容,更多關(guān)于typescript type分配條件類型的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
TypeScript數(shù)據(jù)結(jié)構(gòu)鏈表結(jié)構(gòu)?LinkedList教程及面試
這篇文章主要為大家介紹了TypeScript數(shù)據(jù)結(jié)構(gòu)鏈表結(jié)構(gòu)?LinkedList教程及面試,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02ThreeJS使用紋理貼圖創(chuàng)建一個我的世界草地方塊
這篇文章主要為大家介紹了ThreeJS使用紋理貼圖創(chuàng)建一個我的世界草地方塊的實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06Manipulation-TypeScript?DOM操作示例解析
這篇文章主要為大家介紹了DOM?Manipulation-TypeScript?DOM操作示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03