Предполагая, что вы хотите выполнить замену "все сразу", а не как "цепочку" (это означает, что вы не собираетесь, скажем, заменить X
на Y
и , затем замените Y
на Z
), затем вы можете переписать DeepReplace
, чтобы получить объединение M
наборов сопоставлений, соответствующих [Condition1, Replacement1] | [Condition2, Replacement2] | ...
. Таким образом, ваш старый DeepReplace<T, C, R>
будет DeepReplace<T, [C, R]>
. Определение будет выглядеть так:
type DeepReplace<T, M extends [any, any]> = {
[P in keyof T]: T[P] extends M[0]
? Replacement<M, T[P]>
: T[P] extends object
? DeepReplace<T[P], M>
: T[P];
}
, где Replacement<M, T>
находит кортеж сопоставления в M
, где T
присваивается условию и возвращает соответствующую замену, и определяется следующим образом:
type Replacement<M extends [any, any], T> =
M extends any ? [T] extends [M[0]] ? M[1] : never : never;
Давайте посмотрим, работает ли он на некоторых типах, которые я здесь сделаю. Учитывая следующее:
interface DateLike {
v: Date;
}
interface StringLike {
v: string;
}
interface NumberLike {
v: number;
}
interface Original {
a: {
dat: DateLike;
str: StringLike;
num: NumberLike;
boo: boolean
},
b: {
arr: NumberLike[]
},
c: StringLike,
d: number
}
Давайте заменим ...Like
типы:
type Replaced = DeepReplace<Original,
[DateLike, Date] | [StringLike, string] | [NumberLike, number]
>
/* equivalent to
type Replaced = {
a: {
dat: Date;
str: string;
num: number;
boo: boolean;
};
b: {
arr: number[];
};
c: string;
d: number;
}
*/
Так что это работает.
Обратите внимание, что вызов нового DeepReplace<T, [C, R]>
, вероятно, имеет те же граничные случаи, что и исходный DeepReplace<T, C, R>
. Например, союзы типа {a: string | DateLike}
не будут отображаться. Я подумаю, что любая их настройка выходит за рамки вопроса.
Хорошо, надеюсь, это поможет; удачи!
Детская площадка ссылка на код