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:
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!