为递归数据定义数据类型的操作不正确

时间:2020-01-09 16:08:03

标签: typescript

在为数据定义适当的types时遇到问题。我有一个包含以下数据的对象数组,我的任务是根据数据的结构给出适当的types

export const DashboardSections = [
    {
        name: 'Dashboard',
        sectionItems: [
            {
                title: 'Dashboard',
                icon: 'FaHome',
                path: adminUrl,
                type: 'link',
                active: true,
                children: [],
            },
            {
                title: 'Products',
                icon: 'FaBox',
                path: `${adminUrl}/products`,
                type: 'sub',
                active: false,
                children: [
                    {
                        path: `${adminUrl}/products`,
                        title: 'Products',
                        type: 'link',
                        active: false,
                        children: [],
                    },
                    {
                        path: `${adminUrl}/categories`,
                        title: 'Categories',
                        type: 'link',
                        active: false,
                        children: [],
                    },
                    // Tags are more specific (describe your posts in more detail)
                    {
                        path: `${adminUrl}/tags`,
                        title: 'Tags',
                        type: 'link',
                        active: false,
                        children: [],
                    },
                    {
                        path: `${adminUrl}/attributes`,
                        title: 'Attributes',
                        type: 'link',
                        active: false,
                        children: [],
                    },
                ],
            },
            {
                title: 'Menus',
                icon: 'FaThLarge',
                path: `${adminUrl}/menus`,
                type: 'link',
                active: false,
                children: [],
            },
        ],
    },
    {
        name: 'System',
        sectionItems: [
            {
                title: 'Appearance',
                icon: 'FaPalette',
                path: `${adminUrl}/sliders`,
                type: 'sub',
                active: false,
                children: [],
            },
        ],
    },
];

我认为根项目之后的数据具有递归结构。所以我已经这样定义types

type link = 'link' | 'sub';

type rootDashItem = {
    /** Title of the root item */
    title: string;
    /** Only root item could contain a svg **/
    icon: string;
    /** Path of the root item */
    path: string;
    /** Root item could be a 'link' i.e. don't have any children(empty array) or 'sub' means has array of children. */
    type: link;
    /** Item would be active or not */
    active: boolean;
    /** Contain array of sub items */
    children: subDashItem[];
};


type subDashItem = {
    title: string;
    path: string;
    type: link;
    active: boolean;
    children: subDashItem[];
};


export type dashSection = {
    name: string;
    sectionItems: rootDashItem[];
};

但是当我尝试在其他地方重用type

const items = DashboardSections.map((section: dashSection ) => {
     return section.sectionItems.filter((item: rootDashItem) => {
        if (item.active) {
            return {...item, section: section.name}
        }
    });

Linter在DashboardSections.map((section: dashSection )行上引发错误。

Error:(130, 37) TS2345: Argument of type '(section: dashSection) => rootDashItem[]' is not assignable to parameter of type '(value: { name: string; sectionItems: { title: string; icon: IconType; path: string; type: string; active: boolean; children: { path: string; title: string; type: string; active: boolean; children: never[]; }[]; }[]; }, index: number, array: { ...; }[]) => rootDashItem[]'.
  Types of parameters 'section' and 'value' are incompatible.
    Type '{ name: string; sectionItems: { title: string; icon: IconType; path: string; type: string; active: boolean; children: { path: string; title: string; type: string; active: boolean; children: never[]; }[]; }[]; }' is not assignable to type 'dashSection'.
      Types of property 'sectionItems' are incompatible.
        Type '{ title: string; icon: IconType; path: string; type: string; active: boolean; children: { path: string; title: string; type: string; active: boolean; children: never[]; }[]; }[]' is not assignable to type 'rootDashItem[]'.
          Type '{ title: string; icon: IconType; path: string; type: string; active: boolean; children: { path: string; title: string; type: string; active: boolean; children: never[]; }[]; }' is not assignable to type 'rootDashItem'.
            Types of property 'type' are incompatible.
              Type 'string' is not assignable to type 'link'.

我做错了什么?为递归结构定义类型的更好方法是什么?

完整代码:

const adminUrl = "http://localhost:3000/admin";


//#region Types

type link = 'link' | 'sub';

type subDashItem = {
    title: string;
    path: string;
    type: link;
    active: boolean;
    children: subDashItem[];
};



type rootDashItem = {
    /** Title of the root item */
    title: string;
    /** Only root item could contain a svg **/
    icon: string;
    /** Path of the root item */
    path: string;
    /** Root item could be a 'link' i.e. don't have any children(empty array) or 'sub' means has array of children. */
    type: link;
    /** Item would be active or not */
    active: boolean;
    /** Contain array of sub items */
    children: subDashItem[];
};




export type dashSection = {
    name: string;
    sectionItems: rootDashItem[];
};
//#endregion Types


//#region Item Structure
export const DashboardSections = [
    {
        name: 'Dashboard',
        sectionItems: [
            {
                title: 'Dashboard',
                icon: '',
                path: adminUrl,
                type: 'link',
                active: true,
                children: [],
            },
            {
                title: 'Products',
                icon: '',
                path: `${adminUrl}/products`,
                type: 'sub',
                active: false,
                children: [
                    {
                        path: `${adminUrl}/products`,
                        title: 'Products',
                        type: 'link',
                        active: false,
                        children: [],
                    },
                    {
                        path: `${adminUrl}/categories`,
                        title: 'Categories',
                        type: 'link',
                        active: false,
                        children: [],
                    },
                    // Tags are more specific (describe your posts in more detail)
                    {
                        path: `${adminUrl}/tags`,
                        title: 'Tags',
                        type: 'link',
                        active: false,
                        children: [],
                    },
                    {
                        path: `${adminUrl}/attributes`,
                        title: 'Attributes',
                        type: 'link',
                        active: false,
                        children: [],
                    },
                ],
            },
            {
                title: 'Menus',
                icon: '',
                path: `${adminUrl}/menus`,
                type: 'link',
                active: false,
                children: [],
            },
        ],
    },
    {
        name: 'System',
        sectionItems: [
            {
                title: 'Appearance',
                icon: '',
                path: `${adminUrl}/sliders`,
                type: 'sub',
                active: false,
                children: [],
            },
        ],
    },
];

//#endregion Item Structure

// Challenge is to take those root items which are active with its corresponding section title
const items = DashboardSections.map((section: dashSection ) => {
     return section.sectionItems.filter((item: rootDashItem) => {
        if (item.active) {
            return {...item, section: section.name}
        }
    });

});

console.log(items);

Live link

1 个答案:

答案 0 :(得分:1)

您只需要注释DashboardSections的类型:

export const DashboardSections: Array<dashSection> = [/*...*/]

然后在section.sectionItems.filter((item: rootDashItem) => ...中修复过滤器回调。过滤器函数应返回boolean。因此,您可能想按item.active进行过滤,然后再次按map进行过滤,以根据需要转换项目。

Here's the code