#A little help on getting recursive generic type to work

7 messages · Page 1 of 1 (latest)

wheat steppeBOT
#
matsuuu_#0

Preview:```ts
type Route = ViewRoute | ChildRoute

interface ViewRoute {
path: string
name: string
children?: readonly ChildRoute[]
}

interface ChildRoute extends ViewRoute {
isChild: true
}

interface Options<R extends Route> {
routes: readonly R[]
}
...```

scenic wagon
#

I'm looking for help on trying to get a recursive generic type to work on my class. Currently it can recognize params for the function "getRouteByName" on the top level, but I would want it to allow also the names of the child-routes

hollow sorrel
# scenic wagon I'm looking for help on trying to get a recursive generic type to work on my cla...
type Route = ViewRoute | ChildRoute;

interface ViewRoute {
  path: string;
  name: string;
  children?: readonly ChildRoute[];
}

interface ChildRoute extends ViewRoute {
  isChild: true;
}

interface Options<R extends Route> {
  routes: readonly R[];
}

// Recursive type to extract all names, including from children
type RouteNames<R extends Route> = R["name"] | (R extends { children: readonly Route[] } ? RouteNames<R["children"][number]> : never);

class RouteCollection<R extends Route> {
  routes: readonly R[] = [];

  constructor(options: Options<R>) {
    this.routes = options.routes;
  }

  getRouteByName<N extends RouteNames<R>>(name: N): R | undefined {
    const findRoute = (routes: readonly Route[]): R | undefined => {
      for (const route of routes) {
        if (route.name === name) {
          return route as R;
        }
        if (route.children) {
          const childMatch = findRoute(route.children);
          if (childMatch) {
            return childMatch;
          }
        }
      }
      return undefined;
    };

    return findRoute(this.routes);
  }
}

// Example usage
const routes = [
  {
    path: "/",
    name: "Home",
    children: [
      {
        path: "/sub",
        name: "SubHome",
        isChild: true,
      },
    ],
  },
  {
    path: "/foo",
    name: "Foo",
  },
] as const;

const coll = new RouteCollection({ routes });

const home = coll.getRouteByName("Home"); // Type: ViewRoute
const foo = coll.getRouteByName("Foo"); // Type: ViewRoute
const subHome = coll.getRouteByName("SubHome"); // Type: ChildRoute

console.log({home, foo, subHome})

output

{
  "home": {
    "path": "/",
    "name": "Home",
    "children": [
      {
        "path": "/sub",
        "name": "SubHome",
        "isChild": true
      }
    ]
  },
  "foo": {
    "path": "/foo",
    "name": "Foo"
  },
  "subHome": {
    "path": "/sub",
    "name": "SubHome",
    "isChild": true
  }
} 
scenic wagon
#

Perfect, thank you so much!

#

Somehow I had ignored using the types like this. I've still yet to delve this deep into creating recursive types and generics

hollow sorrel
scenic wagon
#

Yeah this was just a mockup of my complete setup, so that's why it's a barebones, "dumbed down" example