Skip to content

Type of matches (MetaMatches) is imprecise #13507

Open
@michaelboyles

Description

@michaelboyles

I'm using React Router as a...

framework

Reproduction

https://stackblitz.com/edit/github-yk2hokfb-9fz5u2rm?file=app%2Froutes%2Fproject.tsx

System Info

n/a

Used Package Manager

npm

Expected Behavior

Go to project.tsx which is inside a layout. Look at the type of matches (the ellipses are from Monaco, not from me, but hopefully you get the gist):

[{
    id: "root";
    params: {} & {
        [key: string]: string | undefined;
    };
    pathname: string;
    meta: MetaDescriptor[];
    data: undefined;
    handle?: unknown;
    error?: unknown;
}, {
    ...;
}, {
    ...;
}, ...({
    ...;
} | undefined)[]]

The actual array of matches at runtime is an array of length 3: (root, projects, project)

With this type, you can index at e.g. matches[10], even though there will never be that many matches.

Actual Behavior

That part at the end shouldn't be there.

...({
    ...;
} | undefined)

The problematic type is defined here:

https://github.com/remix-run/react-router/blame/20f51f45dbce89c09da807601ca2b19d2fef8373/packages/react-router/lib/types/route-module.ts#L54

It's hard to reverse engineer intent of how a type was written, so hopefully @pcattori can comment on this.

I believe the type should be this

type MetaMatches<T extends RouteInfo[]> = { [K in keyof T]: T[K] extends RouteInfo ? MetaMatch<T[K]> : never };

This is better for a few reasons. It allows correct bounds checking (the typechecker won't let you write matches[10] now, while you could before), and it removes that | undefined which as far as my tests found is never a valid value anyway.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions