Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Statically Typed Links not working when passing href #47689

Open
1 task done
MrHus opened this issue Mar 30, 2023 · 22 comments
Open
1 task done

Statically Typed Links not working when passing href #47689

MrHus opened this issue Mar 30, 2023 · 22 comments
Labels
area: app App directory (appDir: true) bug Issue was opened via the bug report template. TypeScript Related to types with Next.js.

Comments

@MrHus
Copy link

MrHus commented Mar 30, 2023

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: darwin
      Arch: x64
      Version: Darwin Kernel Version 21.6.0: Mon Dec 19 20:44:01 PST 2022; root:xnu-8020.240.18~2/RELEASE_X86_64
    Binaries:
      Node: 18.15.0
      npm: 9.5.0
      Yarn: N/A
      pnpm: N/A
    Relevant packages:
      next: 13.2.5-canary.21
      eslint-config-next: 13.2.4
      react: 18.2.0
      react-dom: 18.2.0

Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true), TypeScript

Link to the code that reproduces this issue

https://codesandbox.io/p/sandbox/angry-scott-twxtz4?file=%2F.next%2Ftypes%2Flink.d.ts&selection=%5B%7B%22endColumn%22%3A17%2C%22endLineNumber%22%3A32%2C%22startColumn%22%3A17%2C%22startLineNumber%22%3A32%7D%5D

To Reproduce

I've been trying server components with the new "app" directory with the typedRoutes: true config set too true.

It generates the following: routes definitions in the Next.js folder:

 type StaticRoutes = 
    | `/`
    | `/pokedex`
    | `/pokedex/create`
    | `/todo`
    | `/weather`
    | `/404.page`
    | `/404.test`
    | `/500.test`
    | `/500.page`
  type DynamicRoutes<T extends string = string> = 
    | `/pokedex/${SafeSlug<T>}`
    | `/pokedex/${SafeSlug<T>}/evolutions`
    | `/pokedex/${SafeSlug<T>}/edit`
    | `/weather/${SafeSlug<T>}`
    | `/api/${OptionalCatchAllSlug<T>}`

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

I get a TypeScript error in a component called <Pager> it creates a two button
pagination component:

import Link from 'next/link';
import { Page } from '../../types';
import { Route } from 'next';

type Props<T extends string> = {
  page: Page<unknown>;
  hrefForPage(page: string): Route<T> | URL;
};

export function Pager<T extends string>(props: Props<T>) {
  const { page } = props;

  if (page.first && page.last) {
    return null;
  }

  const prevPage = `${page.number - 1}`;
  const nextPage = `${page.number + 1}`;

  return (
    <div>
      <Link href={props.hrefForPage(prevPage)}>
        <button disabled={page.first}>prev</button>
      </Link>
      <Link href={props.hrefForPage(nextPage)}>
        <button disabled={page.last}>next</button>
      </Link>
    </div>
  );
}

The idea behind the hrefForPage is that it is a callback function, which should return the proper url for
the next and previous Link, given the page number as a string.

This differs from the beta documentation example, as that example passes the href directly, with no function in between.

Note: that I also have components which do pass the href like in the documentation, and this works like a charm.

TypeScript does not however agree that the hrefForPage returns the correct type:

> tsc --version && tsc --noEmit

Version 5.0.2
src/components/Pager/Pager.tsx:22:13 - error TS2322: Type 'URL | Route<T>' is not assignable to type 'UrlObject | RouteImpl<URL>'.
  Type 'T extends `/pokedex/${SafeSlug<infer _ extends string>}` | `/pokedex/${SafeSlug<infer _ extends string>}/edit` | `/pokedex/${SafeSlug<infer _ extends string>}/evolutions` | `/weather/${SafeSlug<infer _ extends string>}` | ... 10 more ... | `/api/${OptionalCatchAllSlug<...>}#${string}` ? T : never' is not assignable to type 'UrlObject | RouteImpl<URL>'.
    Type '(`/pokedex/${string}` | `/pokedex/${string}/edit` | `/pokedex/${string}/evolutions` | `/weather/${string}` | `/api/${string}` | `/pokedex/${string}?${string}` | `/pokedex/${string}#${string}` | `/pokedex/${string}/edit?${string}` | `/pokedex/${string}/edit#${string}` | `/pokedex/${string}/evolutions?${string}` | `/p...' is not assignable to type 'UrlObject | RouteImpl<URL>'.
      Type '`/pokedex/${string}` & T' is not assignable to type 'UrlObject | RouteImpl<URL>'.
        Type '`/pokedex/${string}` & T' is not assignable to type 'UrlObject'.
          Type 'T extends `/pokedex/${SafeSlug<infer _ extends string>}` | `/pokedex/${SafeSlug<infer _ extends string>}/edit` | `/pokedex/${SafeSlug<infer _ extends string>}/evolutions` | `/weather/${SafeSlug<infer _ extends string>}` | ... 10 more ... | `/api/${OptionalCatchAllSlug<...>}#${string}` ? T : never' is not assignable to type 'UrlObject'.
            Type '(`/pokedex/${string}` | `/pokedex/${string}/edit` | `/pokedex/${string}/evolutions` | `/weather/${string}` | `/api/${string}` | `/pokedex/${string}?${string}` | `/pokedex/${string}#${string}` | `/pokedex/${string}/edit?${string}` | `/pokedex/${string}/edit#${string}` | `/pokedex/${string}/evolutions?${string}` | `/p...' is not assignable to type 'UrlObject'.
              Type '`/pokedex/${string}` & T' is not assignable to type 'UrlObject'.
                Types of property 'search' are incompatible.
                  Type '{ (regexp: string | RegExp): number; (searcher: { [Symbol.search](string: string): number; }): number; }' is not assignable to type 'string'.

22       <Link href={props.hrefForPage(prevPage)}>
               ~~~~

  .next/types/link.d.ts:78:5
    78     href: __next_route_internal_types__.RouteImpl<T> | UrlObject
           ~~~~
    The expected type comes from property 'href' which is declared here on type 'IntrinsicAttributes & LinkRestProps & { href: UrlObject | RouteImpl<URL>; }'

src/components/Pager/Pager.tsx:25:13 - error TS2322: Type 'URL | Route<T>' is not assignable to type 'UrlObject | RouteImpl<URL>'.

25       <Link href={props.hrefForPage(nextPage)}>
               ~~~~

  .next/types/link.d.ts:78:5
    78     href: __next_route_internal_types__.RouteImpl<T> | UrlObject
           ~~~~
    The expected type comes from property 'href' which is declared here on type 'IntrinsicAttributes & LinkRestProps & { href: UrlObject | RouteImpl<URL>; }'


Found 2 errors in the same file, starting at: src/components/Pager/Pager.tsx:22

Describe the Bug

TypeScript gives an error whenever a callback function returns Route<T> | URL when passing the result of that callback function to the href prop of the Link component.

Expected Behavior

I expect that TypeScript thinks that the result of a function that returns Route<T> | URL should be valid.

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

@MrHus MrHus added the bug Issue was opened via the bug report template. label Mar 30, 2023
@github-actions github-actions bot added area: app App directory (appDir: true) TypeScript Related to types with Next.js. labels Mar 30, 2023
@DuCanhGH
Copy link
Contributor

DuCanhGH commented Mar 30, 2023

I can't reproduce this, there's no errors on my end. Can you upload your tsconfig.json? Thanks!

@JesseKoldewijn
Copy link
Contributor

@DuCanhGH his tsconfig is present in the codesandbox:

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "incremental": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "plugins": [
      {
        "name": "next"
      }
    ]
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}

@DuCanhGH
Copy link
Contributor

Perhaps you can try something like this?

import { Route } from "next";
import Link from "next/link";

import { Page } from "../types";

type Props = {
  page: Page<unknown>;
  hrefForPage<T extends string>(page: string): Route<T> | URL;
};

export function Pager(props: Props) {
  // ...
}

or you can assert the type to TS by using <Link<T> /> instead of <Link /> :) Both seem to work fine for me.

@MrHus
Copy link
Author

MrHus commented Mar 30, 2023

@DuCanhGH

Doing that breaks another component called BackButton:

import Link from 'next/link';
import { Route } from 'next';

/**
 * The BackButton component renders back button which is a
 * <Link> under the hood.
 */
export function BackButton<T extends string>({ href }: Props<T>) {
  return (
    <Link href={href}>
      Back
    </Link>
  );
}

Gives me the following error:

> hands-on-react-front-end@1.0.0 tsc
> tsc --version && tsc --noEmit

Version 5.0.2
src/components/BackButton/BackButton.tsx:17:11 - error TS2322: Type '"/404.page" | "/404.test" | "/500.page" | "/500.test" | "/" | "/pokedex" | "/weather" | "/todo" | `/404.page?${string}` | `/404.page#${string}` | `/404.test?${string}` | `/404.test#${string}` | `/500.page?${string}` | `/500.page#${string}` | `/500.test?${string}` | `/500.test#${string}` | ... 25 more ... | URL' is not assignable to type 'UrlObject | RouteImpl<URL>'.
  Type '`/pokedex/${string}`' is not assignable to type 'UrlObject | RouteImpl<URL>'.

17     <Link href={href}>
             ~~~~

  .next/types/link.d.ts:78:5
    78     href: __next_route_internal_types__.RouteImpl<T> | UrlObject
           ~~~~
    The expected type comes from property 'href' which is declared here on type 'IntrinsicAttributes & LinkRestProps & { href: UrlObject | RouteImpl<URL>; }'


Found 1 error in src/components/BackButton/BackButton.tsx:17

@DuCanhGH
Copy link
Contributor

DuCanhGH commented Mar 30, 2023

@MrHus seems unrelated to each other, but a weird issue nonetheless as there's literally a test with the exact same component... Deleting | URL seems to work fine, but why is that even the case?

@MrHus
Copy link
Author

MrHus commented Mar 30, 2023

The issue appears only when applying your fix, before that error does not appear.

@DuCanhGH
Copy link
Contributor

@MrHus I still see the issue without that change applied, perhaps there was something wrong with tsc.

@MrHus
Copy link
Author

MrHus commented Mar 30, 2023

The BackButton was wrong it should be:

export function BackButton<T extends string>({ href }: { href: Route<T> | URL }) {
  return (
    <Link href={href}>
      Back
    </Link>
  );

It does not fix the Pager.

Btw running in the "codesandbox" the command: "npm run tsc" is what also gives the error.

@DuCanhGH
Copy link
Contributor

DuCanhGH commented Mar 30, 2023

@MrHus I copied the code into a new Next project and the error still appears. It is probable that something changed between TS 4.8 and 5.0 that caused TS to infer the generic for Link to be URL. Next's test is passing without any TS errors for Card, yet that component makes TS scream in this new project. Well, if anything, you can pull out the good old reliable <Link<T> /> to force TS to use T for Link's generic argument instead of URL.

@bfourgeaud
Copy link

I do also get an error when my Link is pointing to the root directory "/"
Type '"/"' is not assignable to type 'UrlObject | RouteImpl<"/">'

<Link href="/">
  Go Back
</Link>

To remove the error I have to either point to another route which is not the root one, or pass the pathname :

<Link href='/back'>
  Retourner au menu
</Link>
<Link href={{ pathname: "/" }}>
  Retourner au menu
</Link>

@Cielquan
Copy link
Contributor

Cielquan commented Apr 18, 2023

The issue also applies to the official app-dir-i18n-routing example.

Reproduction

  1. Create a new project derived from the example
  2. Add typedRoutes: true to next.config.js
  3. TS will yell at line 23 in app/[lang]/components/locale-switcher.tsx, where a dynamic href is passed to <Link>: Type 'string' is not assignable to type 'UrlObject'.ts(2322)

Tried changes

1. Typing of inner function

When I change line 10:

- const redirectedPathName = (locale: string) => {
+ const redirectedPathName = <T extends string>(locale: string): Route<T> | URL => {

I get Errors on line 11 and 14 where strings are returned, but the Link component href is fine:

Type '"/"' is not assignable to type '(T extends `/${SafeSlug<infer _ extends string>}` | `/${SafeSlug<infer _ extends string>}?${string}` | `/${SafeSlug<infer _ extends string>}#${string}` ? T : never) | URL'.ts(2322)

2. Typing of Link component

When I change line 8 and line 24:

- export default function LocaleSwitcher() {
+ export default function LocaleSwitcher<T extends string>() {
...
- <Link href={redirectedPathName(locale)}>{locale}</Link>
+ <Link<Route<T> | URL> href={redirectedPathName(locale)}>{locale}</Link>

I get a similar error to the original one (shorted version copied from VSCode tooltip):

Type 'string' is not assignable to type 'UrlObject | ((T extends `/${SafeSlug<infer _ extends string>}` | `/${SafeSlug<infer _ extends string>}?${string}` | `/${SafeSlug<infer _ extends string>}#${string}` ? T : never) extends `/${SafeSlug<...>}` | ... 1 more ... | `/${SafeSlug<...>}#${string}` ? (`/${SafeSlug<...>}` | ... 1 more ... | `/${SafeSlug<...>}#$...'.ts(2322)

EDIT: If I remove the .next/types directory no error is shown.

@SofiuzzamanSofi
Copy link

SofiuzzamanSofi commented Jun 12, 2023

ERROR:

Type 'string | undefined' is not assignable to type 'UrlObject | RouteImpl<string | undefined>'.
  Type 'undefined' is not assignable to type 'UrlObject | RouteImpl<string | undefined>'.ts(2322)
link.d.ts(89, 5): The expected type comes from property 'href' which is declared here on type 'IntrinsicAttributes & LinkRestProps & { href: UrlObject | RouteImpl<string | undefined>; }'
(property) href: UrlObject | __next_route_internal_types__.RouteImpl<string | undefined>
The path or URL to navigate to. This is the only required prop. It can also be an object.

@see — [https://nextjs.org/docs/api-reference/next/link](vscode-file://vscode-app/c:/Users/sofiu/AppData/Local/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html)

Code:

import Link from 'next/link';
import { FC } from 'react';
import { UrlObject } from 'url';


interface CommonButtonProps {
    buttonText: string;
    buttonType?: string;
    buttonGo?: UrlObject | string;
}

const CommonButton: FC<CommonButtonProps> = ({ buttonText, buttonType, buttonGo }) => {
    return (
        <div className="mt-8 text-center">
            {buttonType === 'Link' ? (
                <Link href={buttonGo} className=" bg-green-600 hover:bg-green-500 text-white py-4 px-6 rounded-lg uppercase">
                    {buttonText}
                </Link>
            ) : (
                <button className="bg-green-600 hover:bg-green-500 text-white py-4 px-6 rounded-lg uppercase">
                    {buttonText}
                </button>
            )}
        </div>
    );
};

export default CommonButton;

Lastly i try to found solution and come to consider:

<Link href={{ pathname: buttonGo }}

@JesseKoldewijn
Copy link
Contributor

ERROR:

Type 'string | undefined' is not assignable to type 'UrlObject | RouteImpl<string | undefined>'.
  Type 'undefined' is not assignable to type 'UrlObject | RouteImpl<string | undefined>'.ts(2322)
link.d.ts(89, 5): The expected type comes from property 'href' which is declared here on type 'IntrinsicAttributes & LinkRestProps & { href: UrlObject | RouteImpl<string | undefined>; }'
(property) href: UrlObject | __next_route_internal_types__.RouteImpl<string | undefined>
The path or URL to navigate to. This is the only required prop. It can also be an object.

@see — [https://nextjs.org/docs/api-reference/next/link](vscode-file://vscode-app/c:/Users/sofiu/AppData/Local/Programs/Microsoft%20VS%20Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html)

Code:

import Link from 'next/link';
import { FC } from 'react';
import { UrlObject } from 'url';


interface CommonButtonProps {
    buttonText: string;
    buttonType?: string;
    buttonGo?: UrlObject | string;
}

const CommonButton: FC<CommonButtonProps> = ({ buttonText, buttonType, buttonGo }) => {
    return (
        <div className="mt-8 text-center">
            {buttonType === 'Link' ? (
                <Link href={buttonGo} className=" bg-green-600 hover:bg-green-500 text-white py-4 px-6 rounded-lg uppercase">
                    {buttonText}
                </Link>
            ) : (
                <button className="bg-green-600 hover:bg-green-500 text-white py-4 px-6 rounded-lg uppercase">
                    {buttonText}
                </button>
            )}
        </div>
    );
};

export default CommonButton;

Lastly i try to found solution and come to consider:

<Link href={{ pathname: buttonGo }}

You're not doing a nullcheck on the buttonGo entry. Which because of it being a optional entry results in the "string | undefined" type.

@Ransomware0
Copy link

In file next.config.js, deactivate typedRoutes:

typedRoutes: false

@shuding
Copy link
Member

shuding commented Aug 18, 2023

As the docs says (link), you'll have to either infer the correct link type, or cast it to Route so Next.js can statically check it.

In this example, you have buttonGo?: UrlObject | string and then pass it to <Link href={buttonGo}>. It means you are allowing any string to be the href of a link which is obviously a TS error:

interface CommonButtonProps {
    buttonText: string;
    buttonType?: string;
    buttonGo?: UrlObject | string;
}

const CommonButton: FC<CommonButtonProps> = ({ buttonText, buttonType, buttonGo }) => {
    return (
        <div className="mt-8 text-center">
            {buttonType === 'Link' ? (
                <Link href={buttonGo} className=" bg-green-600 hover:bg-green-500 text-white py-4 px-6 rounded-lg uppercase">
                    {buttonText}
                </Link>
            ) : (
                <button className="bg-green-600 hover:bg-green-500 text-white py-4 px-6 rounded-lg uppercase">
                    {buttonText}
                </button>
            )}
        </div>
    );
};

You can either do <Link href={buttonGo as Route}> to avoid the TS error or make the type inference work:

interface CommonButtonProps<T extends string> {
    buttonText: string;
    buttonType?: string;
    buttonGo?: UrlObject | Route<T>;
}

function CommonButton<T extends string>({ buttonText, buttonType, buttonGo }: CommonButtonProps<T>) {
    return (
        <div className="mt-8 text-center">
            {buttonType === 'Link' ? (
                <Link href={buttonGo} ...

@chrisb2244
Copy link

I get a TS error in a similar situation trying to write the following:

app/presentation-list/page.tsx

import { redirect } from "next/navigation"
import { currentWebsiteYear } from "@/lib/databaseModels"
import type { Route } from "next"

const PresentationPage = () => {
  const targetPage: Route = `/presentation-list/${currentWebsiteYear}`
  redirect(targetPage)
}

export default PresentationPage

Folder layout:

app/presentation-list/
- page.tsx
- layout.tsx
- [year]/page.tsx

link.d.ts file shortened extract (multiple lines deleted) after npm run build (which succeeds):

  type StaticRoutes = 
    | `/`
    | `/presentation-list`
  type DynamicRoutes<T extends string = string> = 
    | `/presentation-list/${SafeSlug<T>}`

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

It seems like Next is happy-ish with the type here (whilst retrying, now it doesn't build...), but TS is complaining. Restarting the TS server doesn't change this. Since the input for redirect allows a string, my hope was that specifically having a Route typing here would avoid a possible typo (especially if I change the paths in future), but I get

Type '"/presentation-list/2020" | "/presentation-list/2021" | "/presentation-list/2022" | "/presentation-list/2023"' is not assignable to type 'Route'.
  Type '"/presentation-list/2020"' is not assignable to type 'Route'. Did you mean '"/presentation-list"'

I wondered if the typing of currentWebsiteYear was the problem (it is typed as "2020" | "2021" | "2022" | "2023"), but the following has the same issue:

const targetPage: Route = `/presentation-list/${currentWebsiteYear as string}`
Type '`/presentation-list/${string}`' is not assignable to type 'Route'

Renaming the /presentation-list/page.tsx to prevent that being a valid path doesn't fix the dynamic path, but does lead to a build error in another Link which links to /presentation-list (as expected).

Creating a Link object seems to be ok, at least in this case, but a generic function is not:

import type { Route } from "next"
import Link from "next/link"

const PresentationPage = () => {
  const targetPage: Route = `/presentation-list/${currentWebsiteYear}` // error
  const fnPage = <T extends string>(year: AllowedYear): Route<T> | URL => `/presentation-list/${year}` // same error
  const l = <Link href={`/presentation-list/${currentWebsiteYear}`} /> // no error
  redirect(targetPage)
}

Is this expected behaviour at this point? (and is it expected to change as this becomes less experimental?) The typescript error message seems to suggest that these should be allowed as '/presentation-list/${SafeSlug<T>}'.

@karlhorky
Copy link
Contributor

You can either do <Link href={buttonGo as Route}>

@shuding this type assertion currently fails with the @typescript-eslint/no-unnecessary-type-assertion rule (eg. if buttonGo is a string):

This assertion is unnecessary since it does not change the type of the expression. eslint(@typescript-eslint/no-unnecessary-type-assertion)
Screenshot 2023-09-13 at 19 08 03

This is a fairly new issue, since a few releases I think. Maybe I should create an issue.

@karlhorky
Copy link
Contributor

karlhorky commented Sep 13, 2023

or make the type inference work:

interface CommonButtonProps<T extends string> {
    buttonText: string;
    buttonType?: string;
    buttonGo?: UrlObject | Route<T>;
}

function CommonButton<T extends string>({ buttonText, buttonType, buttonGo }: CommonButtonProps<T>) {
    return (
        <div className="mt-8 text-center">
            {buttonType === 'Link' ? (
                <Link href={buttonGo} ...

A variation on this is what we ended up doing in our application.

Here's our version, using the imported LinkProps, with more verbose generic argument / parameter names - this will cause CardLink[href] to be type checked the same way that Link[href] is:

import Link, { LinkProps } from 'next/link';

type CardLinkProps<RouteInferred> = LinkProps<RouteInferred>;

function CardLink<Route>(props: CardLinkProps<Route>) {
  return (
    <div className="m-3 inline-block">
      <Link href={props.href}>
        {props.children}
      </Link>
    </div>
  );
}

@karlhorky
Copy link
Contributor

karlhorky commented Sep 13, 2023

Here's another version, in case you want to have a nested data structure containing multiplle hrefs:

import Link, { LinkProps } from 'next/link';

type Props<RouteInferred> = {
  links: {
    title: string;
    href: LinkProps<RouteInferred>['href'];
  }[];
};

export default function Links<Route>(props: Props<Route>) {
  return (
    <div>
      {props.links.map((link) => {
        return <Link href={link.href}>{link.title}</Link>;
      })}
    </div>
  );
}

Or, using Route, a bit more verbose, but also works:

import { Route } from 'next';
import Link from 'next/link';

type Props<RouteInferred extends string> = {
  links: {
    title: string;
    href: Route<RouteInferred>;
  }[];
};

export default function Links<Route extends string>(props: Props<Route>) {
  return (
    <div>
      {props.links.map((link) => {
        return <Link href={link.href}>{link.title}</Link>;
      })}
    </div>
  );
}

@rusakovic
Copy link

Hello @karlhorky
Maybe you could help to solve this typescript issue?

"next": "13.4.19",

{
  experimental: {
    serverActions: true,
    typedRoutes: true,
  },
 }
import { usePathname , useRouter } from "next/navigation";

const Comp = () => {
const router = useRouter();
const pathname = usePathname();


// Argument of type 'string' is not assignable to parameter of type 'RouteImpl<string>'.ts(2345)
 router.push(pathname)
}

Thank you!

@mannybecerra
Copy link
Contributor

myProp?: UrlObject | Route<T>

This was exactly what I needed — thx as always @shuding

@skusez
Copy link

skusez commented Oct 22, 2023

Hello @karlhorky Maybe you could help to solve this typescript issue?

"next": "13.4.19",

{
  experimental: {
    serverActions: true,
    typedRoutes: true,
  },
 }
import { usePathname , useRouter } from "next/navigation";

const Comp = () => {
const router = useRouter();
const pathname = usePathname();


// Argument of type 'string' is not assignable to parameter of type 'RouteImpl<string>'.ts(2345)
 router.push(pathname)
}

Thank you!

Not ideal but this fixes the linter

router.push(url as Route)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: app App directory (appDir: true) bug Issue was opened via the bug report template. TypeScript Related to types with Next.js.
Projects
None yet
Development

No branches or pull requests