接上文type challenge(easy局部)
对于调配条件类型,官网文档形容地址。
之前看的时候没真正了解,对于联结类型的调配条件,官网文档其实也没有讲得很明确,和翻译无关,英文文档一样很含糊,这些天做type challenge
,发现有些题做进去的后果和预期不太统一,所以从新梳理这块内容。
先说论断
联结类型什么时候会调配,必须合乎4个条件(前面间接用条件1、条件2等代指上面条件):
首先,只调配extends前的内容
- 无论这个extends是不是子断言语句中的
- 例如
type Test<T> = 'b' extends 'b' ? (T extends 'b' ? true: false) : false;
, 其中的T extends 'b'
在子语句中,但事实上仍旧是无效的
调配的内容未做任何解决
type Test<T> = keyof T extends null ? never: false;
,T
被keyof
操作符解决了,因而不会调配- 官网文档中,提到防止调配的办法
type ToArrayNonDist<Type> = [Type] extends [any] ? Type[] : never;
,能躲避调配也是这个情理
- 调配内容必须作为参数传入
- 传入时是联结类型
相干题目与解析
验证条件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
发现这个问题是在DeepReadonly,题目地址
这一题一看看过来,间接写出如下:
type DeepReadonly<T> = keyof T extends never ? T : {readonly [k in keyof T]: DeepReadonly<T[k]>};
然而发现对于测试用例X2
不失效
type X2 = { a: string } | { b: number };DeepReadonly<X2> // { a: string } | { b: number }
认真看,尽管X2是联结类型,但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
不会触发主动调配
type Test = 'a'|'b' extends 'a' ? true: false; // false
那么,假如传入的参数是联结类型,extends
前的对象也是联结类型呢?
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
这里,参数T
是联结类型,但extends
前进行了keyof
解决,但keyof {a:1,b:string}|{a:2,b:number}
后果为'a'|'b'
,仍然是联结类型,若这里进行了主动调配,后果应是boolean
而非false
。
依据后果来看,这里并未进行调配,这个例子同时违反了条件2和条件3
验证条件4
type Test<T> = 'a'|'b' extends 'b' ? T: false;Test<5> // false
条件4不言而喻,官网文档上曾经说的很明确了。
不留神优先级导致的谬误
在测试调配条件类型的法则时,曾因为一条用例卡了半天,用例如下:
type A = keyof null|undefined; // undefinedtype UndefinedExtendsNull = undefined extends null ? true: false; //falsetype Test<T> = keyof T extends null ? true: false;Test<null|undefined>; // true !!!!
此时曾经晓得了,keyof T
会防止主动调配,因而对于Test<null|undefined>
,能够写成
keyof null|undefined extends null ? true : false; // 这里有个坑...
而keyof null|undefined
后果是undefined
,然而
type UndefinedExtendsNull = undefined extends null ? true: false; //false
后果是false
,同样的式子,后果不一样,一开始我认为是调配法则的了解有问题,但即便调配了,后果也应该是true|false
,也就是boolean
,而不是true
。
起初发现,type
是有优先级的,且keyof
优先级高于|
.
按理说keyof null|undefined
后果应该是never
,之所以会显示后果是undefined
,是因为优先级运算:
keyof null|undefined -> (keyof null)|undefined -> never|undefined -> undefined
在理论写类型的时候,要重点留神优先级问题