Сопоставьте объект с другим в Typescript

У меня есть объект роли, который я хотел сопоставить с объектом TreeNode с помощью PrimeNG, чтобы отобразить его в дереве. Ролевой объект выглядит примерно так (тоже показано на картинке)

role: [
id: ....
name: ....
   description: ....
   roles[]: .....
]

объект роли

Объект узла дерева имеет следующую структуру:

{
"data": 
[
    {
        "label": "Documents",
        "data": "Documents Folder",
        "expandedIcon": "fa-folder-open",
        "collapsedIcon": "fa-folder",
        "children": [{
                "label": "Work",
                "data": "Work Folder",
                "expandedIcon": "fa-folder-open",
                "collapsedIcon": "fa-folder",
                "children": [{"label": "Expenses.doc", "icon": "fa-file-word-o", "data": "Expenses Document"}, {"label": "Resume.doc", "icon": "fa-file-word-o", "data": "Resume Document"}]
            },
            {
                "label": "Home",
                "data": "Home Folder",
                "expandedIcon": "fa-folder-open",
                "collapsedIcon": "fa-folder",
                "children": [{"label": "Invoices.txt", "icon": "fa-file-word-o", "data": "Invoices for this month"}]
            }]
    },
    {
        "label": "Pictures",
        "data": "Pictures Folder",
        "expandedIcon": "fa-folder-open",
        "collapsedIcon": "fa-folder",
        "children": [
            {"label": "barcelona.jpg", "icon": "fa-file-image-o", "data": "Barcelona Photo"},
            {"label": "logo.jpg", "icon": "fa-file-image-o", "data": "PrimeFaces Logo"},
            {"label": "primeui.png", "icon": "fa-file-image-o", "data": "PrimeUI Logo"}]
    },
    {
        "label": "Movies",
        "data": "Movies Folder",
        "expandedIcon": "fa-folder-open",
        "collapsedIcon": "fa-folder",
        "children": [{
                "label": "Al Pacino",
                "data": "Pacino Movies",
                "children": [{"label": "Scarface", "icon": "fa-file-video-o", "data": "Scarface Movie"}, {"label": "Serpico", "icon": "fa-file-video-o", "data": "Serpico Movie"}]
            },
            {
                "label": "Robert De Niro",
                "data": "De Niro Movies",
                "children": [{"label": "Goodfellas", "icon": "fa-file-video-o", "data": "Goodfellas Movie"}, {"label": "Untouchables", "icon": "fa-file-video-o", "data": "Untouchables Movie"}]
            }]
    }
]

}

 data.roles.forEach((role, index) => {
        //this.roleTree.label = role.Name;
        //this.roleTree.data = role.ID;

        let treeNode: TreeNode = {
            label: role.Name,
            data: role

        }

        this.treeNodes.push(treeNode);
        console.log(role);
        console.log(index);

    });

Но этот код кажется слишком сложным, когда я пытаюсь сопоставить «роли» в «роли» с «дочерними элементами» в treeNode. Я видел несколько примеров, например это, но отображает те же имена полей.

Я новичок в Typesript, есть ли обходной путь для преобразования моего объекта роли с ролями в treeNode с дочерними элементами, указав мое имя поля (например, имя), которое будет сопоставлено с 'меткой' роли?

Был бы очень признателен пример кода.


person sam    schedule 01.09.2017    source источник
comment
У вас есть interface для вашего типа роли или для типа TreeNode? Допускает ли TreeNode произвольный объект для его свойства data и является ли его children массивом TreeNode?   -  person jcalz    schedule 01.09.2017
comment
и какого типа элементы свойства roles? Они того же типа, что и объект role?   -  person jcalz    schedule 02.09.2017


Ответы (1)


Что ж, я не уверен на 100% насчет используемых вами типов Role и TreeNode. Вот мое предположение, основанное на коде вашего вопроса.

Role имеет несколько важных для вас свойств, но самое сложное - это свойство roles, которое, как я предполагаю, предназначено для массива из Role объектов:

interface Role {
  id: string;
  name: string;
  description: string;
  roles: Role[];
}

Точно так же TreeNode имеет некоторые свойства, но самое сложное - это свойство children, которое представляет собой массив объектов TreeNode. Кроме того, я предполагаю, что TreeNode является общим для типа data, и в этом случае вы хотите сделать TreeNode<Role>, что означает, что свойство data будет объектом Role:

interface TreeNode<T> {
  label: string;
  data: T;
  expandedIcon?: string;
  collapsedIcon?: string;
  children: TreeNode<T>[];
}

Если они верны, вы можете использовать следующую функцию roleToTreeNode() для сопоставления объекта Role с объектом TreeNode<Role>:

function roleToTreeNode(role: Role): TreeNode<Role> {
  return {
    label: role.name,
    data: role,
    children: role.roles.map(roleToTreeNode)
  };
}

Строка children: является оперативной частью функции: вы берете массив role.roles и сопоставляете каждый элемент Role с TreeNode<Role>, что и делает функция roleToTreeNode(). То есть roleToTreeNode() - это рекурсивная функция, которая вызывает сама себя.

Имеет ли это смысл? Надеюсь, это поможет. Удачи!

person jcalz    schedule 02.09.2017
comment
Выглядит неплохо, но позвольте мне попробовать и я вам еще вернусь. - person sam; 04.09.2017
comment
Это работает как шарм, большое спасибо. Но у меня есть другой вопрос. Не могли бы вы объяснить, как работает roleToTreeNode? У меня много детей в дочерних массивах, как они сопоставляют все с одним элементом? - person TheWandererr; 18.04.2018
comment
Это рекурсивно. Тело roleToTreeNode() создает литерал объекта, свойство children которого собирается путем вызова roleToTreeNode для каждого элемента role.roles. Вы можете делать это итеративно с помощью цикла for вместо использования метода массива map(), но это то же самое. Рекурсия. - person jcalz; 18.04.2018
comment
@jcalz вот мой ответ на ввод, ожидающий того же результата, что и в вопросе. [{ "$id": "1", "cityId": 2, "cityName": "India", "Description": "India", "parentId": 0, "cities": [{ "$id": "2", "cityId": 3, "cityName": "delhi", "Description": "delhi", "parentId": 1, "cities": [ {child}, {child} ] } ] }] - person Irfan Syed; 10.05.2018
comment
ссылка мне помогла следующая ссылка выполнение рекурсии и получение моего ответа - person Irfan Syed; 11.05.2018