(ただし有用な場面はそんなにないです)
infer に同じ名前を指定すると、ユニオン型になる
基本的に、infer に同じ名前を指定すると、それらをうまく満たすようなユニオン型になります。
以下の X1,X2,X3 はすべて number | string
です。
type X1 = [number, string] extends [infer x, infer x] ? x : never; type X2 = [number[], string] extends [(infer x)[], infer x] ? x : never; type X3 = [(args: number) => number, string] extends [(args: any) => infer x, infer x] ? x : never;
関数の引数に対しては例外的な挙動をする
上に書いたように、基本的にはユニオンになるのですが、関数の引数部分で infer x を入れると異なる挙動をします。
type X4 = [(args: number) => number, string] extends [(args: infer x) => any, infer x] ? x : never; // never になる type X5 = [(args: number) => number, (args: string) => number] extends ( [(args: infer x) => any, (args: infer x) => any] ) ? x : never; // これも never になる
おそらく関数の引数が反変であることに起因しています。
TypeScript の実際のコードを読んでないので以下は僕の推察なのですが、おそらく 最初の infer x (区別するため x1 とします)と2つ目の infer x (x2) は、 x1 <: x2 かつ x1 >: x2 を満たす必要があるとか、そういう理由なんじゃないかと思ってます。ちょっと分からないのでどなたか調査お願いします。