Общий тип TypeScript, который принимает (1) дерево и (2) тип, с которым все узлы дерева должны стать объединением - PullRequest
0 голосов
/ 07 ноября 2019

Допустим, у меня есть произвольный тип дерева:

type Tree = {
  a: {
    b: {
      c: "d"
    }
  }
}

И тип, с которым я хотел бы сделать каждый узел дерева объединением. Например, "f". Другими словами, дерево должно выглядеть следующим образом:

type Tree = {
  a: {
    b: {
      c: "d" | "f"
    } | "f"
  } | "f"
} | "f"

Моя цель - создать этот тип, используя тип утилиты - возможно, что-то вроде DescendantsUnionedWith<T, F>, где T это может быть тип Tree сверху, а F может быть "f".

Чтобы решить эту проблему, я сначала создал общий тип ChildrenUnionedWith:

export type ChildrenUnionedWith<O extends object, T> = {
  [K in keyof O]: O[K] | T;
};

Затем я попытался создать рекурсивный тип с глубиной дерева:

export type DescendantsUnionedWith<Tree extends object, T> = Tree extends object
  ? ChildrenUnionedWith<DescendantsUnionedWith<Tree, T>, T>
  : Tree | T;

Результатом, конечно, была ошибка округлости: /

Кто-нибудь знает способ, которым я могу достичьDescendantsUnionedWith тип утилиты?

Спасибо!

1 Ответ

1 голос
/ 07 ноября 2019

Это должно работать .... игнорируйте то, что он говорит, тип выходит, поскольку он не читает то, что он есть на самом деле. тесты ниже ....

Дайте мне знать, если есть какие-либо проблемы.

type DeepUpdate<T, Append> = {
  [K in keyof T]: T[K] extends object ? DeepUpdate<T[K], Append> | Append : T[K] | Append
}

type Tree = {
  a: {
    b: {
      c: "d"
    }
  }
}


type IsEqual<A, B> = [A] extends [B] ? [B] extends [A] ? true : false : false


type test = IsEqual<DeepUpdate<Tree, "F">, {
  a: {
    b: {
      c: "d" | "F"
    } | "F"
  } | "F"
}>; // true.


...