Это можно сделать - но какой ценой?
Возможно, стоит попробовать посмотреть, есть ли способ сделать то, что вы хотите, более простым способом. Здесь не так много контекста, поэтому я не могу посоветовать, как вы подойдете к этому - обычно я стараюсь держаться подальше от подобных вещей по причинам ремонтопригодности.
Это сделает то, о чем вы просите - где T - это тип объекта для преобразования, TTarget - это Type1, а TResult - это NewType
First - более простая форма, которая лениво вычисляет. Это означает, что вы получите следующий результат при наведении курсора на тип результата:
1008 *
type Transform1 = {
[key in keyof T]:
T[key] extends object
? Transform1
: T[key] extends TTarget ? TReplacement : T[key];
}
This version will eagerly evaluate the nested object - giving you more 'correct' looking type hints
type Transform2 = {
[key in keyof T]:
T[key] extends object
? {
[innerKey in keyof Transform2]:
Transform2[innerKey]
}
: T[key] extends TTarget ? TReplacement : T[key];
}
How this works is that we first map over T using a mapped type -
{ [key in keyof T]: T[key] }
Next we need to check if T[key] is a nested object, and if so - we need to recurse the type. We do this by asking if T[key] extends object
. If it does, Transform
again.
Then we can check if T[key] is assignable to the TTarget we are trying to replace with T[key] extends TTarget
. If it does, return TReplacement, otherwise leave it alone by returning T[key].
The eagerly evaluated version just uses a little trick where we map over the result type again.
We are doing the same {[key in T]: T[key]}
- except we replace T with the thing we want to evaluate - which is Transform
. We also need another variable for key, because we're now mapping over the inner type, so I used innerKey here.
This gives us
{ [innerKey in keyof Transform2]: Transform2[innerKey] }
Playground link:
https://www.typescriptlang.org/play?#code / C4TwDgpgBAKuEEYoF4oGdgCcCWA7A5gNwBQoks8ATClAEYD29ANhAIa4lnQByEA7nHKpcAVwC2tCJhLE8wKQDNWAY2gBJXPMxLVSAN7EoUMJnpgEALgqQEh46bCUrgiJTsmzAZisGjRtCK0HubO8LZ + 6IHBTtaudgC + xImymooq6qna6dS + 9maWULwC8O4OMS5uRsHeULn + UQ4FRS529UFloZCVUInJAPR9sAAW2GhQfNhMTFBMrABekyBQEABurEwirPJQwEPQuBAYEAAmUPS0AFYQysCk8LCY7GgK9JhiCAA8MMsAHvK4xzG5yuNwANLAYKxMPgIMBwTAAEoQMCzVRiCCaAB8NDqUAA2gBrCBLPBQIkgegKWAAXQsrQisEJxOpv3 + gLOl2utwZPKgAH4Hk8Xm9PjAmSBqfDIdDYfCkSj0uisfTeVBnOKWRA-hj2TBpTDgPzYPLURAlYb1eTqSR4lBiMQBsNRuNJtM2DDMEwlqt1pttrt9od5KdgVyoABaKD4bArPD4KAUkRQMSvaAAcmUr0wXLTM0YBLjO3uI00aDu5Bgj1wz1eYkoX1ZOqBnLBEKhBrlyNN5uxqFx4qgpPJlJpdNVYqtjYBzZB3NVfgFuPnfjxeAOmAA0sTB7gycSR5WhbX6xPmVL27LjV3FRjgJjaSrlwzD9XhXWvhrzzK4VeFWjb5iq64OuW4So + qqJE + aqMpOWpsmMeoXoaAqIte -6aNBp4Sjadr2o6AAS9ArFIZzEZgUBIgETDAEgwD0OgEDQFwUAlrczGUSI1FIKgL41iKHwaFoOiIPCYTgs08CYjIBFESRsnkRx1HUHRDFMiin76cjAn * 10CYJBFESRsnkRx1HUHRDFMiC1CJP * 10CYNFMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXVX