Итак, у меня есть эта вспомогательная функция, которая позволяет мне заменять типы на основе структурного соответствия:
type Replace<T, C, A> = {
[P in keyof T]: T[P] extends C ? A : T[P]
}
Это позволяет мне делать следующее:
type NumberThing = { value: number }
type StringThing = Replace<NumberThing, number, string>
const a: StringThing = { value: "cenas" }
Все хорошо и Денди, пока кто-нибудь не сделает это:
type ArrayOfNumberThing = { value: Array<number> }
Хорошо, я просто добавляю новое условие ...
type Replace<T, C, A> = {
[P in keyof T]: T[P] extends C ? A : (T[P] extends Array<C> ? Array<A> : T[P])
}
И оно набирает:
type ArrayOfNumberThing = { value: Array<number>, simpleValue: number }
type ArrayOfStringThing = Replace<ArrayOfNumberThing, number, string>
const b: ArrayOfStringThing = { value: ["cenas"], simpleValue: "still works" }
Но этот парень упрям, и теперь бросает мне:
type CrazyNumberThing = { value: Array<Array<Array<number>>> }
Ну, я всегда мог бы сделать это:
type RecursiveArrayReplace<T, C, A> = T extends C ? A : (T extends Array<infer E> ? RecursiveArrayReplace<E, C, A> : T)
... который, очевидно, будет глубоко изучать Массив, пока не найдет то, что хочет заменить, верно? Правильно? Неправильно:
Type alias 'RecursiveArrayReplace' circularly references itself.
И прежде чем я смог вытереть слезы, кто-то просто бросил мне:
type TupleStringNumberThing = { value: [string, number] }
... что заставляет меня свернуться в позе зародыша, если вы, ребята, помоги мне: (