Home > Software design >  Configuration based React Router in TypeScript throwing eslint errors
Configuration based React Router in TypeScript throwing eslint errors

Time:01-24

Okay, as I look through the docs for React Router, errors as displayed in VS Code

What's wrong there? I've typed myRouter. I get that the array is untyped for createBrowserRouter, but I thought it could infer.

But let's pull it out and strongly type that array.

import React from 'react';
import ReactDOM from 'react-dom/client';
import type { RouteObject } from 'react-router';
import type { BrowserRouter } from 'react-router-dom';
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import AnItem from './components/Shared/AnItem';

const routes: RouteObject[] = [
    {
        path: '/',
        element: <AnItem />,
    },
];

const myRouter: BrowserRouter = createBrowserRouter(routes);

ReactDOM.createRoot(document.getElementById('root')!).render(
    <React.StrictMode>
        <RouterProvider router={myRouter} />
    </React.StrictMode>
);

Now it's happy through routes but still yells at me for...

const myRouter: BrowserRouter = createBrowserRouter(routes);

Unsafe assignment of an any value.

VS Code popover explaining the Unsafe assignment of an any value.

Where is the any? Is it from createBrowserRouter somehow? If I mouseover in VS Code, I get "intellisense" (if that's still what it's called), so I think my types, etc, are all mapping correctly:

(alias) createBrowserRouter(routes: RouteObject[], opts?: {
    basename?: string | undefined;
    hydrationData?: Partial<Pick<RouterState, "loaderData" | "actionData" | "errors">> | undefined;
    window?: Window | undefined;
} | undefined): Router
import createBrowserRouter

That says pretty clearly it returns a Router.

It looks like it can't figure out what BrowserRouter is from that type BrowserRouter = /*unresolved*/ any. But when I mouseover the import, I get:

(alias) function BrowserRouter({ basename, children, window, }: BrowserRouterProps): JSX.Element
import BrowserRouter
A <Router> for use in web browsers. Provides the cleanest URLs.

'BrowserRouter' is declared but its value is never read.ts(6133)

So that seems in context too, though the "its value is never read" is surprising.

Now I did try to type myRouter as a Router, but I get yelled at that I should use a more specific type of router:

Note: You usually won't render a directly [sic]. Instead, you'll render a router that is more specific to your environment such as a in web browsers or a for server rendering.

So I'm using BrowserRouter. But its error is:

'BrowserRouter' refers to a value, but is being used as a type here. Did you mean 'typeof BrowserRouter'?

I'm pretty sure I don't mean typeof; I'm defining a variable as a specifc type.

What am I missing here? I'm having a hard time googling up an example that both uses configuration instead of components for routing (and I think configuration is what I want as the new Data History API routers require it) and is in TypeScript.

Looks like Drew's on to something. Here are my dependencies from package.json:

    "dependencies": {
        "bootstrap": "^5.2.3",
        "react": "^18.2.0",
        "react-bootstrap": "^2.7.0",
        "react-dom": "^18.2.0",
        "react-router": "^6.7.0",
        "react-router-dom": "^6.7.0"
    },
    "devDependencies": {
        "@types/react": "^18.0.26",
        "@types/react-dom": "^18.0.9",
        "@typescript-eslint/eslint-plugin": "^5.48.2",
        "@typescript-eslint/parser": "^5.48.2",
        "@vitejs/plugin-react-swc": "^3.0.0",
        "eslint": "^8.32.0",
        "eslint-config-prettier": "^8.6.0",
        "eslint-config-xo": "^0.43.1",
        "eslint-config-xo-typescript": "^0.55.1",
        "eslint-plugin-react": "^7.32.1",
        "opener": "^1.5.2",
        "typescript": "^4.9.4",
        "vite": "^4.0.0"
    }

Update: If I disable those rules and take out the typing, things do render as I'd expect.

  • Related