Click here to Skip to main content
15,881,882 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
 error TS2322: Type 'MenuItem[] | undefined' is not assignable to type 'MenuItem[]'

I'm working on a windows 10 machine and using vscode editor to write my typescript code. However, Next.js with typescript build fails with Error: Type 'MenuItem[] | undefined' is not assignable to type 'MenuItem[]' (see the last line of code which is where the error occurs). 

First of all, here is contents of the package.json file:


{
  "private": true,
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start",
    "type-check": "tsc",
    "lint": "next lint"
  },
  "dependencies": {
    "@styled-icons/material": "^10.34.0",
    "next": "^12.1.6",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "styled-components": "5.3.5",
    "tslib": "^2.4.0"
  },
  "devDependencies": {
    "@types/node": "^12.12.21",
    "@types/react": "^17.0.2",
    "@types/react-dom": "^17.0.1",
    "@types/styled-components": "^5.1.25",
    "@typescript-eslint/eslint-plugin": "^5.26.0",
    "eslint": "7.32.0",
    "eslint-config-next": "^12.1.6",
    "typescript": "4.3.2",
    "typescript-transform-jsx": "^1.5.5"
  }
}


Here is the contents of the tsconfig.json file:

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx",
    "components/MenuItem"
  ],
  "exclude": [
    "node_modules"
  ]
}


Here is the contents of the next.config.js file:

 /** @type {import('next').NextConfig} */
module.exports = {
  reactStrictMode: true,
}


This is a copy of the MenuItem index,tsx file that has the line of code
{isExpanded && isNested ? <MenuItemsList options={subItems} /> : null}


import Link from "next/link";
import { useRouter } from "next/router";
import { MenuItem as MenuItemType } from "../../constants/menu-items";
import { MenuItemContainer } from "./MenuItem.styles";
import MenuItemsList from "../MenuItemsList";
import ExpandIcon from "../ExpandIcon";
import { useState } from "react";

type MenuItemProps = {
  menuItem: MenuItemType;
};

export default function MenuItem({
  menuItem: { name, icon: Icon, url, depth, subItems },
}: MenuItemProps) {
  const [isExpanded, toggleExpanded] = useState(false);

  const router = useRouter();
  const selected = router.asPath === url;
  const isNested = subItems && subItems?.length > 0;

  const onClick = () => {
    toggleExpanded((prev) => !prev);
  };

  return (
    <>
      <MenuItemContainer className={selected ? "selected" : ""} depth={depth}>
        <Link href={url} passHref>
          <div className="menu-item">
            <Icon />
            <span>{name}</span>
          </div>
        </Link>
        {isNested ? (
          <ExpandIcon isExpanded={isExpanded} handleClick={onClick} />
        ) : null}
      </MenuItemContainer>
      {isExpanded && isNested ? <MenuItemsList options={subItems} /> : null}
    </>
  );
}


This is a copy of the MenuItemsList index,tsx file:


import { MenuItem as MenuItemType } from "../../constants/menu-items";
import MenuItem from "../MenuItem";
import { ListContainer } from "./MenuItemsList.styles";

type MenuItemsListProps = {
  options: MenuItemType[];
};

export default function MenuItemsList({ options }: MenuItemsListProps) {
  return (
    <ListContainer>
      {options.map((option) => (
        <MenuItem menuItem={option} key={option.id} />
      ))}
    </ListContainer>
  );
}


And here is the code in file menu-items.ts referred to in the export default line in
MenuItem.

import React from "react";
import {
  Dashboard,
  ShoppingCart,
  People,
  AttachMoney,
  AddShoppingCart,
  Done,
  Business,
  HomeWork,
  Person,
} from "@styled-icons/material";

const MENU_OPTIONS: MenuOption[] = [
  {
    name: "Dashboard",
    icon: Dashboard,
    url: "/",
  },
  {
    name: "Orders",
    icon: ShoppingCart,
    url: "/orders",
    subItems: [
      {
        name: "New",
        icon: AddShoppingCart,
        url: "/new-orders",
      },
      {
        name: "Completed",
        icon: Done,
        url: "/completed-orders",
      },
    ],
  },
  {
    name: "Customers",
    icon: People,
    url: "/customers",
    subItems: [
      {
        name: "Corporate",
        icon: Business,
        url: "/corporate",
      },
      {
        name: "SMB",
        icon: HomeWork,
        url: "/smb",
        subItems: [
          {
            name: "Retail",
            icon: Person,
            url: "/retail",
          },
        ],
      },
    ],
  },
  {
    name: "Inventory",
    icon: AttachMoney,
    url: "/inventory",
  },
];

export type MenuItem = {
  name: string;
  icon: React.ComponentType;
  url: string;
  id: string;
  depth: number;
  subItems?: MenuItem[];
};

type MenuOption = {
  name: string;
  icon: React.ComponentType;
  url: string;
  subItems?: MenuOption[];
};

function makeMenuLevel(options: MenuOption[], depth = 0): MenuItem[] {
  return options.map((option, idx) => ({
    ...option,
    id: depth === 0 ? idx.toString() : `${depth}.${idx}`,
    depth,
    subItems:
      option.subItems && option.subItems.length > 0
        ? makeMenuLevel(option.subItems, depth + 1)
        : undefined,
  }));
}

export const MENU_ITEMS: MenuItem[] = makeMenuLevel(MENU_OPTIONS);


What I have tried:

I've searched the internet to try to find any reference to anything in my code that could explain the error I'm receiving when executing npm run build, but I haven't found an answer. Also, I ran the debugger on all of the files and they all came up clean.

Please help!
Posted
Updated 31-May-22 11:56am
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900