我具有以下联合类型:
type Test =
| {
type: 'Union'
items: Array<
| { type: 'Number' }
| { type: 'String' }
| { type: 'Union'; items: Array<{ type: 'Number' } | { type: 'Boolean' }> }
>
}
| { type: 'Date' }
我希望结果是:
type Result =
| { type: 'Number' }
| { type: 'String' }
| { type: 'Boolean' }
| { type: 'Date' }
由于循环引用的限制,以下内容无效:
type Flatten<T> = T extends { type: 'Union'; items: unknown[] }
? Flatten<T['items'][number]>
: T
是否可以使用接口或其他替代方法来解决?
答案 0 :(得分:2)
据我所知(截至TS3.5),no supported technique通常会执行递归条件类型函数。通常,如果圆度涉及将类型下推到嵌套属性中,但是不支持将类型 out 拉出嵌套属性,则可以。我尝试过(或看过尝试过)欺骗编译器接受这些事情的所有“聪明”技巧都以悲伤告终。
通常,当我想要一个像这样的递归类型时,我要做的是选择某种合理的递归深度来进行纾困。在这种情况下,您期望T
通常位于Flatten<T>
中的嵌套深度是多少……假设最多六层?好吧,在这种情况下,我们可以将圆形类型展开为一系列非圆形类型,这些类型最终会碰到砖墙:
type Flatten<T> = T extends { type: 'Union'; items: unknown[] } ? Flatten1<T['items'][number]> : T;
type Flatten1<T> = T extends { type: 'Union'; items: unknown[] } ? Flatten2<T['items'][number]> : T;
type Flatten2<T> = T extends { type: 'Union'; items: unknown[] } ? Flatten3<T['items'][number]> : T;
type Flatten3<T> = T extends { type: 'Union'; items: unknown[] } ? Flatten4<T['items'][number]> : T;
type Flatten4<T> = T extends { type: 'Union'; items: unknown[] } ? Flatten5<T['items'][number]> : T;
type Flatten5<T> = T extends { type: 'Union'; items: unknown[] } ? Flatten6<T['items'][number]> : T;
type Flatten6<T> = T extends { type: 'Union'; items: unknown[] } ? FlattenX<T['items'][number]> : T;
type FlattenX<T> = T; // uh oh bail out
这可能很丑陋,但通常效果可控。让我们看看它如何处理您的类型:
type Result = Flatten<Test>;
// type Result = { type: "Date"; } | { type: "Number"; } |
// { type: "String"; } | { type: "Number"; } | { type: "Boolean"; }
对我很好。好的,希望对您有所帮助。祝你好运!