Преобразование данных из API с помощью TypeScript и Лодашь


Как фронт-энд разработчик, я дал следующий результат из API, массив объектов, который выглядит как:

[{
    Color: "#065b79",
    GroupName: "VXYZ",
    QuoteCount: 4,
    SortOrder: 0,
    TabCategoryID: "CHSI1",
    TabCategoryName: "Workers' Compensation",
    TabCategoryOrder: 0,
    TabID: 1,
    TabName: "new"
}]

Мне нужно, чтобы отобразить данные в более иерархический формат/вложенные:

[{
    GroupName: 'VXYZ',
    TabCategories: [
        {
            TabCategoryID: 'CHSI1',
            TabCategoryName: "Workers' Compensation",
            TabCategoryOrder: 0,
            Tabs: [
                {
                    Color: '#065b79',
                    SortOrder: 0,
                    TabID: 1,
                    TabName: 'new',
                    QuoteCount: 4
                }
            ]
        }
    ]
}]

Любые данные в массив может иметь любое количество элементов массива. В моделях выше, я просто использовать один экземпляр каждого элемента массива.

Это код, который я использовал для форматирования данных

Я с помощью TypeScript и лодашь. API является экспериментальным, и наша политика заключается в том, чтобы просто использовать any типа за любые данные, поступающие от экспериментальных Апис. Это объясняет (Quotes: any) — Это данные от API.

public FormatQuoteSummaries(Quotes: any): any {

    return _(Quotes)
    .map(Quote => Quote.GroupName)
    .uniq()
    .map(UniqueGroupName => {
        const GroupName = UniqueGroupName
        const AllTabCategories = _.filter(Quotes, (Quote: any) => {
            return Quote.GroupName === UniqueGroupName
        })
        const TabCategories = _(AllTabCategories).map(TabCategory => {
            return {
                TabCategoryID: TabCategory.TabCategoryID,
                TabCategoryName: TabCategory.TabCategoryName,
                Tabs: _.filter(Quotes, (Quote: any) => {
                    return Quote.TabCategoryName === TabCategory.TabCategoryName &&
                        Quote.GroupName === TabCategory.GroupName
                })
            }
        })
            .uniqBy('TabCategoryID')
            .value();

        return {
            GroupName,
            TabCategories
        }
    })
    .value();
}


Комментарии
1 ответ

Первое и самое главное, изменить ваши политики об использовании any для нестабильного API-интерфейсы.

TypeScript-это невероятно мощный инструмент, благодаря которому можно работать с постоянно меняющимися API-интерфейсы. При использовании any вы не выбрасываете (почти) всеми преимуществами, которые машинопись дает вам. Если вы объявляете интерфейс для данных, возвращаемых API, вы можете просто изменить интерфейс, когда изменения в формате и вы будете предупреждены, чтобы любой код, который должен быть обновлен. Если вы вместо того, чтобы использовать any ваш код будет компилироваться без каких-либо предупреждений - а потом перерыв в производстве.

Кроме этого, там действительно не так много, чтобы упомянуть. Хорошая работа!

По коду:


  1. Первое, что я сделал, было добавить типы, вот интерфейсы я буду использовать для остальной части ответа:

    interface APITabCategory {
    Color: string;
    GroupName: string;
    QuoteCount: number;
    SortOrder: number;
    TabCategoryID: string;
    TabCategoryName: string;
    TabCategoryOrder: number;
    TabID: number;
    TabName: string;
    }

    interface Tab {
    Color: string;
    SortOrder: number;
    TabID: number;
    TabName: string;
    QuoteCount: number;
    }

    interface TabCategory {
    TabCategoryID: string;
    TabCategoryName: string;
    TabCategoryOrder: number;
    Tabs: Tab[]
    }

    interface TabCategoryCollection {
    GroupName: string;
    TabCategories: TabCategory[]
    }


  2. Это не делать то, что вы думаете он делает. Как только я добавил интерфейсов для ваших типов машинопись наорал на меня, что TabCategoryOrder пропал без вести - это может быть намеренным, как вы сейчас, используя массив, но он входит в свой выходной выборки.

  3. Текущий код включает в себя кучу дополнительных данных в каждом Tabэто нормально, так как машинописный текст, но так как этот код нормализует данных, вы можете рассмотреть возможность удаления лишних свойств.

  4. В JavaScript есть встроенный map и filter функции на массивы, я предпочитаю использовать их лодашь альтернативы, где это уместно. В этом случае он удаляет большую зависимость кода на лодашь.

  5. Избежание двойного условия проверки. Если вы сохраняете цитаты с нынешним названием группы в массив, вы можете избежать проверки имени группы при извлечении вкладки.

  6. Получите программу пылеобразования и использовать его - нынешний кодекс не соответствует ли или не использовать точку с запятой.

Вот как я бы реализовать эту функцию:

function FormatQuoteSummaries(Quotes: APITabCategory[]): TabCategoryCollection[] {
const UniqueGroupNames = _.uniq(Quotes.map(Quote => Quote.GroupName));

return UniqueGroupNames.map(GroupName => {
const GroupQuotes = Quotes.filter(Quote => Quote.GroupName == GroupName)

const TabCategories: TabCategory[] = GroupQuotes
.filter(Quote => Quote.GroupName === GroupName)
.map(({ TabCategoryID, TabCategoryName, TabCategoryOrder }) => {
return {
TabCategoryID,
TabCategoryName,
TabCategoryOrder,
Tabs: GroupQuotes.filter(Quote => Quote.TabCategoryName === TabCategoryName)
};
});

return {
GroupName,
TabCategories: _.uniqBy(TabCategories, 'TabCategoryID')
};
});
}


Один последний небольшой придираться, это достаточно стандартный-это JavaScript / TypeScript, чтобы использовать camelCase в отличие от PascalCase для локальных переменных и свойств. Большинство с JS / ТС разработчики, увидев Quotes ожидать класс / интерфейс / перечисление / пространство имен, а не объект или массив. Не стесняйтесь игнорировать, если ваша команда уже устоявшаяся именования.

3
ответ дан 3 апреля 2018 в 03:04 Источник Поделиться