Next.js Discord

Discord Forum

Statically Typed Link: Route<T> as function result type prevents returning Dynamic Route string

Unanswered
Bombay-duck posted this in #help-forum
Open in Discord
Bombay-duckOP
Statically typed link is amazing and brings a lot of sense of safety. However I ran into issue where I create a function to return a Route<T> and use it to generate valid route links, but have the compiler complaining about returning wrong strings.
The strange thing is that it works when using static route string like /, but doesn't work with dynamic route string like /category/${}.
I check the link.d.ts file and find that the dynamic route strings are created, and it works when used directly as <Link/>'s href.

link.d.ts:
declare namespace __next_route_internal_types__ {
  type SearchOrHash = `?${string}` | `#${string}`
  type WithProtocol = `${string}:${string}`

  type Suffix = '' | SearchOrHash

  type SafeSlug<S extends string> = S extends `${string}/${string}`
    ? never
    : S extends `${string}${SearchOrHash}`
    ? never
    : S extends ''
    ? never
    : S

  type CatchAllSlug<S extends string> = S extends `${string}${SearchOrHash}`
    ? never
    : S extends ''
    ? never
    : S

  type OptionalCatchAllSlug<S extends string> =
    S extends `${string}${SearchOrHash}` ? never : S

  type StaticRoutes = 
    | `/`
    | `/projects`
    | `/tags`
  type DynamicRoutes<T extends string = string> = 
    | `/category/${SafeSlug<T>}`
    | `/series/${SafeSlug<T>}`
    | `/posts/${SafeSlug<T>}`
    | `/projects/${SafeSlug<T>}`
    | `/tags/${SafeSlug<T>}`

  type RouteImpl<T> = 
    | StaticRoutes
    | SearchOrHash
    | WithProtocol
    | `${StaticRoutes}${SearchOrHash}`
    | (T extends `${DynamicRoutes<infer _>}${Suffix}` ? T : never)
    
}

function I'm trying to build
const FilterItemToRoute = <T extends string>(
  item: FilterItem
): Route<T> | URL =>
  match(item.condition)
    .with("category", () => `/category/${item.value}` as const)
    .with("series", () => `/series/${item.value}` as const)
    .exhaustive();

0 Replies