TypeScript не достаточно мощный, чтобы представлять то, что вы пытаетесь сделать.В идеале JavaScript и TypeScript должны иметь оператор слияния нуля , и вы бы это использовали.Но у него этого нет.
Если вы попытаетесь строго набрать метод lodash has
, вы обнаружите, что компилятор не может объединить строковые литералы типов или выполнить операции с регулярными выражениями над ними , поэтому компилятор не может взять строку 'getCoach.workouts.items'
и понять, что getCoach
будет ключом data
, а workouts
будет ключом data.getCoach
и т. д.
Даже без использования has
сложно представить, что здесь происходит манипулирование вложенными типами, не сталкиваясь с проблемами с рекурсией , которые вызывают недовольство компилятораили сбой.
Лучшее, что я могу сделать: обернуть объект в Proxy (требуется ES2015 или новее), который всегда имеет значение для любой клавиши, которую вы хотите использовать, и вы используетеспециальное имя ключа (например, "value"
) для извлечения фактического значения свойства или undefined
, если его нет.Вот реализация:
type WrapProperties<T, K extends keyof any> = Record<K, T> & { [P in keyof T]-?: WrapProperties<T[P], K> }
function wrapProperties<T>(val: T): WrapProperties<T, "value">;
function wrapProperties<T, K extends keyof any>(val: T, valueProp: K): WrapProperties<T, K>;
function wrapProperties(val: any, valueProp: keyof any = "value"): WrapProperties<any, any> {
return new Proxy({}, {
get: (_, p) => p === valueProp ? val : wrapProperties(
(typeof val === 'undefined') || (val === null) ? val : val[p], valueProp
)
});
}
Итак, вместо этого:
if (data && data.getCoach && data.getCoach.workouts && data.getCoach.workouts.items) {
data.getCoach.workouts.items.map((workout) => {/* do something*/})
}
Вы должны быть в состоянии сделать это:
const wrappedData = wrapProperties(data, "val");
if (wrappedData.getCoach.workouts.items.value) {
wrappedData.getCoach.workouts.items.value.map((workout) => {/* do something*/})
}
Я незнать, является ли реализация perfect ;кажется, работает, когда я пытаюсь это сделать.Как и все, что вы получаете от переполнения стека, ваш пробег может варьироваться и будьте бдительны.Может быть, это поможет вам.Удачи!