Skip to content

Commit

Permalink
Tatthurs/nextjs link type (#200)
Browse files Browse the repository at this point in the history
* Update nextjs link types

* Update nextjs link types
  • Loading branch information
tatethurston authored Sep 25, 2024
1 parent a36e8a1 commit 0956f4f
Show file tree
Hide file tree
Showing 11 changed files with 491 additions and 658 deletions.
2 changes: 1 addition & 1 deletion .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pnpm run package:build
pnpm run e2e:setup
pnpm run examples:regen
pnpm run lint:fix
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

- Fix generated routes when using [parallel-routes](https://nextjs.org/docs/app/building-your-application/routing/parallel-routes) and [intercepting-routes](https://nextjs.org/docs/app/building-your-application/routing/intercepting-routes).

- Fix `ref` type for `Link`. Previously `ref` was missing, now it's correctly typed.

## 2.2.1

- Fix route generation on Windows. See [#187](https://github.com/tatethurston/nextjs-routes/issues/187). Thanks @AkanoCA!
Expand Down
103 changes: 47 additions & 56 deletions examples/app/@types/nextjs-routes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,35 +83,26 @@ declare module "nextjs-routes" {
declare module "next/link" {
import type { Route, RouteLiteral } from "nextjs-routes";;
import type { LinkProps as NextLinkProps } from "next/dist/client/link";
import type {
AnchorHTMLAttributes,
DetailedReactHTMLElement,
MouseEventHandler,
PropsWithChildren,
} from "react";
export * from "next/dist/client/link";
import type React from "react";

type StaticRoute = Exclude<Route, { query: any }>["pathname"];

export interface LinkProps
extends Omit<NextLinkProps, "href" | "locale">,
AnchorHTMLAttributes<HTMLAnchorElement> {
export type LinkProps = Omit<NextLinkProps, "href" | "locale"> & {
href: StaticRoute | RouteLiteral;
locale?: false;
}

type LinkReactElement = DetailedReactHTMLElement<
{
onMouseEnter?: MouseEventHandler<Element> | undefined;
onClick: MouseEventHandler;
href?: string | undefined;
ref?: any;
},
HTMLElement
>;

declare function Link(props: PropsWithChildren<LinkProps>): LinkReactElement;

/**
* A React component that extends the HTML `<a>` element to provide [prefetching](https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#2-prefetching)
* and client-side navigation between routes.
*
* It is the primary way to navigate between routes in Next.js.
*
* Read more: [Next.js docs: `<Link>`](https://nextjs.org/docs/app/api-reference/components/link)
*/
declare const Link: React.ForwardRefExoticComponent<Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps> & LinkProps & {
children?: React.ReactNode;
} & React.RefAttributes<HTMLAnchorElement>>;
export default Link;
}

Expand Down Expand Up @@ -181,41 +172,41 @@ declare module "next/navigation" {
export * from "next/dist/client/components/navigation";
import type { RoutedQuery, RouteLiteral } from "nextjs-routes";

/**
* A [Client Component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) hook
* that lets you read the current URL's pathname.
*
* @example
* ```ts
* "use client"
* import { usePathname } from 'next/navigation'
*
* export default function Page() {
* const pathname = usePathname() // returns "/dashboard" on /dashboard?foo=bar
* // ...
* }
* ```
*
* Read more: [Next.js Docs: `usePathname`](https://nextjs.org/docs/app/api-reference/functions/use-pathname)
*/
/**
* A [Client Component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) hook
* that lets you read the current URL's pathname.
*
* @example
* ```ts
* "use client"
* import { usePathname } from 'next/navigation'
*
* export default function Page() {
* const pathname = usePathname() // returns "/dashboard" on /dashboard?foo=bar
* // ...
* }
* ```
*
* Read more: [Next.js Docs: `usePathname`](https://nextjs.org/docs/app/api-reference/functions/use-pathname)
*/
export function usePathname(): RouteLiteral;

/**
* A [Client Component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) hook
* that lets you read a route's dynamic params filled in by the current URL.
*
* @example
* ```ts
* "use client"
* import { useParams } from 'next/navigation'
*
* export default function Page() {
* // on /dashboard/[team] where pathname is /dashboard/nextjs
* const { team } = useParams() // team === "nextjs"
* }
* ```
*
* Read more: [Next.js Docs: `useParams`](https://nextjs.org/docs/app/api-reference/functions/use-params)
*/
/**
* A [Client Component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) hook
* that lets you read a route's dynamic params filled in by the current URL.
*
* @example
* ```ts
* "use client"
* import { useParams } from 'next/navigation'
*
* export default function Page() {
* // on /dashboard/[team] where pathname is /dashboard/nextjs
* const { team } = useParams() // team === "nextjs"
* }
* ```
*
* Read more: [Next.js Docs: `useParams`](https://nextjs.org/docs/app/api-reference/functions/use-params)
*/
export function useParams<Pathname extends Route["pathname"] = Route["pathname"]>(): RoutedQuery<Pathname>;
}
35 changes: 13 additions & 22 deletions examples/cjs/types/nextjs-routes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,35 +83,26 @@ declare module "nextjs-routes" {
declare module "next/link" {
import type { Route } from "nextjs-routes";;
import type { LinkProps as NextLinkProps } from "next/dist/client/link";
import type {
AnchorHTMLAttributes,
DetailedReactHTMLElement,
MouseEventHandler,
PropsWithChildren,
} from "react";
export * from "next/dist/client/link";
import type React from "react";

type StaticRoute = Exclude<Route, { query: any }>["pathname"];

export interface LinkProps
extends Omit<NextLinkProps, "href" | "locale">,
AnchorHTMLAttributes<HTMLAnchorElement> {
export type LinkProps = Omit<NextLinkProps, "href" | "locale"> & {
href: Route | StaticRoute | Omit<Route, "pathname">;
locale?: false;
}

type LinkReactElement = DetailedReactHTMLElement<
{
onMouseEnter?: MouseEventHandler<Element> | undefined;
onClick: MouseEventHandler;
href?: string | undefined;
ref?: any;
},
HTMLElement
>;

declare function Link(props: PropsWithChildren<LinkProps>): LinkReactElement;

/**
* A React component that extends the HTML `<a>` element to provide [prefetching](https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#2-prefetching)
* and client-side navigation between routes.
*
* It is the primary way to navigate between routes in Next.js.
*
* Read more: [Next.js docs: `<Link>`](https://nextjs.org/docs/app/api-reference/components/link)
*/
declare const Link: React.ForwardRefExoticComponent<Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps> & LinkProps & {
children?: React.ReactNode;
} & React.RefAttributes<HTMLAnchorElement>>;
export default Link;
}

Expand Down
35 changes: 13 additions & 22 deletions examples/intl/@types/nextjs-routes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,35 +90,26 @@ declare module "nextjs-routes" {
declare module "next/link" {
import type { Route } from "nextjs-routes";;
import type { LinkProps as NextLinkProps } from "next/dist/client/link";
import type {
AnchorHTMLAttributes,
DetailedReactHTMLElement,
MouseEventHandler,
PropsWithChildren,
} from "react";
export * from "next/dist/client/link";
import type React from "react";

type StaticRoute = Exclude<Route, { query: any }>["pathname"];

export interface LinkProps
extends Omit<NextLinkProps, "href" | "locale">,
AnchorHTMLAttributes<HTMLAnchorElement> {
export type LinkProps = Omit<NextLinkProps, "href" | "locale"> & {
href: Route | StaticRoute | Omit<Route, "pathname">;
locale?: Locale | false;
}

type LinkReactElement = DetailedReactHTMLElement<
{
onMouseEnter?: MouseEventHandler<Element> | undefined;
onClick: MouseEventHandler;
href?: string | undefined;
ref?: any;
},
HTMLElement
>;

declare function Link(props: PropsWithChildren<LinkProps>): LinkReactElement;

/**
* A React component that extends the HTML `<a>` element to provide [prefetching](https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#2-prefetching)
* and client-side navigation between routes.
*
* It is the primary way to navigate between routes in Next.js.
*
* Read more: [Next.js docs: `<Link>`](https://nextjs.org/docs/app/api-reference/components/link)
*/
declare const Link: React.ForwardRefExoticComponent<Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps> & LinkProps & {
children?: React.ReactNode;
} & React.RefAttributes<HTMLAnchorElement>>;
export default Link;
}

Expand Down
35 changes: 13 additions & 22 deletions examples/typescript/types/nextjs-routes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,35 +85,26 @@ declare module "nextjs-routes" {
declare module "next/link" {
import type { Route } from "nextjs-routes";;
import type { LinkProps as NextLinkProps } from "next/dist/client/link";
import type {
AnchorHTMLAttributes,
DetailedReactHTMLElement,
MouseEventHandler,
PropsWithChildren,
} from "react";
export * from "next/dist/client/link";
import type React from "react";

type StaticRoute = Exclude<Route, { query: any }>["pathname"];

export interface LinkProps
extends Omit<NextLinkProps, "href" | "locale">,
AnchorHTMLAttributes<HTMLAnchorElement> {
export type LinkProps = Omit<NextLinkProps, "href" | "locale"> & {
href: Route | StaticRoute | Omit<Route, "pathname">;
locale?: false;
}

type LinkReactElement = DetailedReactHTMLElement<
{
onMouseEnter?: MouseEventHandler<Element> | undefined;
onClick: MouseEventHandler;
href?: string | undefined;
ref?: any;
},
HTMLElement
>;

declare function Link(props: PropsWithChildren<LinkProps>): LinkReactElement;

/**
* A React component that extends the HTML `<a>` element to provide [prefetching](https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#2-prefetching)
* and client-side navigation between routes.
*
* It is the primary way to navigate between routes in Next.js.
*
* Read more: [Next.js docs: `<Link>`](https://nextjs.org/docs/app/api-reference/components/link)
*/
declare const Link: React.ForwardRefExoticComponent<Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps> & LinkProps & {
children?: React.ReactNode;
} & React.RefAttributes<HTMLAnchorElement>>;
export default Link;
}

Expand Down
35 changes: 13 additions & 22 deletions packages/e2e/@types/nextjs-routes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,35 +84,26 @@ declare module "nextjs-routes" {
declare module "next/link" {
import type { Route } from "nextjs-routes";;
import type { LinkProps as NextLinkProps } from "next/dist/client/link";
import type {
AnchorHTMLAttributes,
DetailedReactHTMLElement,
MouseEventHandler,
PropsWithChildren,
} from "react";
export * from "next/dist/client/link";
import type React from "react";

type StaticRoute = Exclude<Route, { query: any }>["pathname"];

export interface LinkProps
extends Omit<NextLinkProps, "href" | "locale">,
AnchorHTMLAttributes<HTMLAnchorElement> {
export type LinkProps = Omit<NextLinkProps, "href" | "locale"> & {
href: Route | StaticRoute | Omit<Route, "pathname">;
locale?: false;
}

type LinkReactElement = DetailedReactHTMLElement<
{
onMouseEnter?: MouseEventHandler<Element> | undefined;
onClick: MouseEventHandler;
href?: string | undefined;
ref?: any;
},
HTMLElement
>;

declare function Link(props: PropsWithChildren<LinkProps>): LinkReactElement;

/**
* A React component that extends the HTML `<a>` element to provide [prefetching](https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#2-prefetching)
* and client-side navigation between routes.
*
* It is the primary way to navigate between routes in Next.js.
*
* Read more: [Next.js docs: `<Link>`](https://nextjs.org/docs/app/api-reference/components/link)
*/
declare const Link: React.ForwardRefExoticComponent<Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps> & LinkProps & {
children?: React.ReactNode;
} & React.RefAttributes<HTMLAnchorElement>>;
export default Link;
}

Expand Down
2 changes: 2 additions & 0 deletions packages/e2e/typetest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ function expectType<T>(_value: T) {}
<Link href={{ query: {} }} replacey />;
// anchor props https://beta.nextjs.org/docs/api-reference/components/link#props
<Link href={{ query: {} }} className="foo" />;
<Link href="/" ref="legacy-ref" />;
<Link href="/" ref={(_ref: HTMLAnchorElement | null) => {}} />;

// LinkProps

Expand Down
2 changes: 1 addition & 1 deletion packages/nextjs-routes/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nextjs-routes",
"version": "2.2.2-rc.3",
"version": "2.2.2-rc.4",
"description": "Type safe routing for Next.js",
"license": "MIT",
"author": "Tate <[email protected]>",
Expand Down
Loading

0 comments on commit 0956f4f

Please sign in to comment.