javascript - Typescript - Jag har problem med att använda ett returvärde från en funktion


Jag vill iterera över en array och kontrollera om en nod har lägre noder och om noden är kompatibel med användarens roll.

Jag tänkte att jag kanske kunde använda "for (let entry of someArray)" för att få varje värde av noden i arrayen, men "someArray" är returvärdet av en funktion:

public menuList(): any {
    return [
        // SCHEDULER
        {
            route: ["", "scheduler"],
            name: "scheduler",
            moduleId: PLATFORM.moduleName("../components/scheduler/scheduler"),
            title: "scheduler",
            nav: true,
            settings: {
                icon: "user",
                roles: ["Employee", "Admin"],
                pos: "left"
            }
        },

        // CLIENTS
        {
            route: "clients",
            name: "clients",
            moduleId: PLATFORM.moduleName("../components/clients/clientList/clientList"),
            title: "Clients",
            nav: true,
            settings: {
                icon: "user",
                roles: ["Employee", "Admin"],
                pos: "left",
                nav: [
                    {
                        route: "clients/ClientsList",
                        name: "clientList",
                        moduleId: PLATFORM.moduleName("../components/clients/clientList/clientList"),
                        href: "#clients/clientsList",
                        title: "Client List",
                        settings: {
                            icon: "list",
                            roles: ["Employee", "Admin"],
                        }
                    },
                    {
                        settings: {
                            roles: ["Employee", "Admin"],
                            divider: true,
                        }
                    },
                    {
                        route: "clients/create",
                        name: "newClient",
                        moduleId: PLATFORM.moduleName("../components/clients/newClient/newClient"),
                        href: "#clients/Create",
                        title: "Create Client",
                        settings: {
                            icon: "user",
                            roles: ["Employee", "Admin"],
                        }
                    }
                ]
            }
        },

        // JOBS
        {
            route: "jobs",
            name: "jobs",
            moduleId: PLATFORM.moduleName("../components/jobs/jobsList"),
            title: "Jobs",
            nav: true,
            settings: {
                icon: "list",
                roles: ["Employee", "Admin"],
                pos: "left"
            },
        },

        // ACCOUNTING

        // Accounting - 1st level route WITH SUBROUTES
        {
            route: "accounting",
            name: "accounting",
            moduleId: PLATFORM.moduleName("../components/accounting/ledgerEnquiry/ledgerEnquiry"),
            title: "Accounting",
            nav: true,
            settings: {
                icon: "usd",
                roles: ["Employee", "Admin"],
                pos: "left",
                nav: [
                    {
                        title: "Creditor Cost Invoices",
                        icon: "tasks",
                        nav: true,
                        roles: ["Employee", "Admin"],
                        settings: {
                            nav: [
                                {
                                    title: 'Creditor Payments',
                                    icon: 'usd',
                                    roles: ["Employee", "Admin"],
                                    settings: {
                                        nav: [
                                            {
                                                route: "accounting/creditorCostInvoices/payments/paymentsRegister",
                                                name: "paymentsRegister",
                                                moduleId: PLATFORM.moduleName("../components/accounting/creditorCostInvoices/payments/paymentsRegister/paymentsRegister"),
                                                href: '#accounting/creditorCostInvoices/payments/paymentsRegister',
                                                title: 'Payments Register',
                                                settings: {
                                                    icon: 'list',
                                                    roles: ["Employee", "Admin"]
                                                }
                                            },
                                            {
                                                settings: {
                                                    roles: ["Employee", "Admin"],
                                                    divider: true,
                                                }
                                            },
                                            {
                                                route: "accounting/creditorCostInvoices/payments/creditorPromptPayments",
                                                name: "promptPayments",
                                                moduleId: PLATFORM.moduleName("../components/accounting/creditorCostInvoices/payments/creditorPromptPayments/creditorPromptPayments"),
                                                href: '#accounting/creditorCostInvoices/payments/creditorPromptPayments',
                                                title: 'Creditor Prompt Payments',
                                                settings: {
                                                    icon: 'usd',
                                                    roles: ["Employee", "Admin"]
                                                }
                                            },
                                            {
                                                route: "accounting/creditorCostInvoices/payments/payOutstandingCreditorInvoices",
                                                name: "payments",
                                                moduleId: PLATFORM.moduleName("../components/accounting/creditorCostInvoices/payments/payOutstandingCreditorInvoices/payOutstandingCreditorInvoices"),
                                                href: '#accounting/creditorCostInvoices/payments/payOutstandingCreditorInvoices',
                                                title: 'Pay Outstanding Creditor Invoices',
                                                settings: {
                                                    icon: 'edit',
                                                    roles: ["Employee"/*, "Admin"*/]
                                                }
                                            },
                                        ],
                                    }
                                },
                            ]
                        }
                    },
                ]
            }
        }
    ]
}

Schemaläggaren är en nod och klienten är en annan, men klienten har en array med tre noder.

Jag vill iterera över detta och skapa en ny array där om någon av noderna inte uppfyller rollvärdet så utelämnas den noden, samtidigt som djupstrukturen i den ursprungliga arrayen bibehålls. Så i menuList() om jag itererar över detta och kontrollerar om rollinställningen har "Admin" och den inte har det, ignoreras den noden och jag får en filtrerad array med bara de noder som har "Admin" i sig.

Jag gjorde en monster "for loop" med inbäddade "for loops" för att försöka fånga detta men misslyckades.

Jag tänkte nu att jag skulle använda let entry of someArray men jag får felet:

Fel TS2349 (TS) Kan inte anropa ett uttryck vars typ saknar en anropssignatur. Typen 'any[]' har inga kompatibla anropssignaturer

Inte säker på hur man fixar detta dock...

Finns det ett smart sätt att filtrera denna array baserat på role.includes("Admin") osv medan strukturen fortfarande bevaras?

UPPDATERING

Jag lyckades äntligen få detta att fungera även om jag tror att det finns en mängd bättre, mer kortfattade sätt att göra det på.

Jag valde att hantera varje nod helt innan jag gick vidare till nästa och för att göra detta använde jag en rekursiv funktion som kallade sig själv för varje nivå.

public userMenu(userName: string, userRole: string): any {
    let finishedRoleCheckedMenu = Array();
    let userMenuElements = Array();
    let returnedElement = {} as any;


    for (const key in this.menuList()) {
        returnedElement = this.processElement(this.menuList()[key], userRole);

        if (returnedElement !== 'undefined') {
            userMenuElements.push(returnedElement);
        }
    }

    for (let count = 0; count < this.routeMenuItems.length; count++) {
        if (!this.routeMenuItems[count].settings.divider) {
            userMenuElements.push(this.routeMenuItems[count]);
        }
    }

    return userMenuElements;
}


processElement(element: any, userRole: string) {
    let testedElement = {} as any;
    let settingsElement = {} as any;
    let navElements = Array();
    let navElement = {} as any;

    if (element.settings.roles.includes(userRole)) {

        for (const key in element) {
            if (key === "settings") {

                for (const settingsKey in element[key]) {
                    if (settingsKey === "nav") {

                        for (const navKey in element[key][settingsKey]) {

                            navElement = this.processElement(element[key][settingsKey][navKey], userRole); // recursive call.

                            if (navElement !== 'undefined') {
                                if (navElement.route) {  // Collect only those elements with routes.
                                    this.routeMenuItems.push(navElement); // For adding the total routes at the end.
                                }
                                navElements.push(navElement);
                            }
                        }
                        if (navElements.length > 0) {

                            settingsElement[settingsKey] = navElements;
                        }
                    } else {
                        settingsElement[settingsKey] = element[key][settingsKey];
                    }
                }
                testedElement[key] = settingsElement;
            } else {
                testedElement[key] = element[key];
            }
        }

        return testedElement;
    } else {
        return 'undefined';
    }
}

Svar #1

Kompilatorn klagar på anroparkoden. Specifikt vad det än planerar att göra med den returnerade arrayen. Anledningen till detta är att du har specificerat returtypen som "any". Kanske kan returtypen av arrayen vara mer lämplig.

När det gäller att filtrera arrayen tror jag att du är på rätt spår, men du skulle kunna städa upp koden lite genom att använda ett map- eller map/reduce-mönster.

Relaterade artiklar