【问题标题】:How to extract type of recursively nested children properties in TypeScript?如何在 TypeScript 中提取递归嵌套子属性的类型?
【发布时间】:2021-04-02 07:59:56
【问题描述】:

我正在尝试对两种类型的节点的递归树关系建模:文本节点和元素节点(如 DOM)。文本节点是树中的叶子,元素节点可以包含其他元素节点或文本节点。

type Text = {
    text: string
}

type Element = {
    children: Node[]
}

type Node = Element | Text

考虑这些节点:

type A = {
    children: Text[]
}

type B = {
    children: A[]
}

type C = {
    children: B[]
}

给定一个特定的Node,我想编写一个实用程序类型,该类型将返回其潜在后代的联合(深)。

只为孩子编写实用程序(浅)很简单:

type ChildOf<N extends Node> = 
    N extends Element
        ? N['children'][number]
        : never

ChildOf<A> // Text
ChildOf<B> // A
ChildOf<C> // B
ChildOf<Text> // never

但是,您将如何编写一个递归实用程序来获取所有深层后代,而不仅仅是浅层子代?

type DescendantOf<N extends Node> = ???

DescendantOf<A> // Text
DescendantOf<B> // A | Text
DescendantOf<C> // A | B | Text
DescendantOf<Text> // never

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您只需在用作递归锚 (playground) 的条件类型中创建 ChildOf&lt;N&gt; 的联合和 DescendantOf 的递归调用:

    type DescendantOf<N> = N extends Node ? ChildOf<N> | DescendantOf<ChildOf<N>> : never;
    
    type descendantA = DescendantOf<A> // Text
    type descendantB = DescendantOf<B> // A | Text
    type descendantC = DescendantOf<C> // A | B | Text
    type descendantText = DescendantOf<Text> // never
    

    递归条件类型的文档可以在here找到。

    编辑:没有ChildOf&lt;N&gt; (playground)的版本:

    type NodeTypes<T> = Extract<T, Node[]>[number];
    type DescendantOf<N extends Node> = N extends {children: infer T} ? NodeTypes<T> | DescendantOf<NodeTypes<T>> : never;
    
    type descendantA = DescendantOf<A> // Text
    type descendantB = DescendantOf<B> // A | Text
    type descendantC = DescendantOf<C> // A | B | Text
    type descendantText = DescendantOf<Text> // never
    

    【讨论】:

    • 哇,谢谢!!我可以发誓我尝试了类似的方法,但没有奏效。结果我不小心使用了旧版本的 TypeScript,我认为这在某种程度上是新支持的。 (以防以后有人犯这个错误!)
    猜你喜欢
    • 2021-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-19
    • 2023-01-30
    • 2019-07-27
    相关资源
    最近更新 更多