Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: molefrog/wouter
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v2.8.0
Choose a base ref
...
head repository: molefrog/wouter
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v2.8.1
Choose a head ref
  • 10 commits
  • 10 files changed
  • 1 contributor

Commits on Nov 3, 2022

  1. Copy the full SHA
    8f943ab View commit details
  2. Update dtslint.

    molefrog committed Nov 3, 2022
    Copy the full SHA
    9d9ad91 View commit details

Commits on Nov 5, 2022

  1. Copy the full SHA
    c112e64 View commit details
  2. Copy the full SHA
    edfb8a0 View commit details
  3. Copy the full SHA
    3f6ab7b View commit details
  4. Copy the full SHA
    79743c6 View commit details
  5. Copy the full SHA
    644b531 View commit details
  6. Copy the full SHA
    90e4b16 View commit details
  7. Copy the full SHA
    04451bf View commit details
  8. Release v2.8.1

    molefrog committed Nov 5, 2022
    Copy the full SHA
    2a4b522 View commit details
Showing with 158 additions and 160 deletions.
  1. +2 −2 package.json
  2. +1 −1 preact/package.json
  3. +4 −8 preact/types/matcher.d.ts
  4. +28 −46 preact/types/ts4.1/index.d.ts
  5. +13 −16 preact/types/ts4.1/type-specs.tsx
  6. +4 −8 types/matcher.d.ts
  7. +13 −12 types/ts3.9.4/index.d.ts
  8. +18 −10 types/ts3.9.4/type-specs.tsx
  9. +37 −41 types/ts4.1/index.d.ts
  10. +38 −16 types/ts4.1/type-specs.tsx
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "wouter",
"version": "2.8.0",
"version": "2.8.1",
"description": "A minimalistic routing for React and Preact. Nothing extra, just HOOKS.",
"keywords": [
"react",
@@ -136,7 +136,7 @@
"@testing-library/react-hooks": "^5.0.3",
"@types/react": "^17.0.1",
"copyfiles": "^2.4.1",
"dtslint": "^3.4.2",
"dtslint": "^4.2.0",
"eslint": "^7.19.0",
"eslint-plugin-react-hooks": "^4.2.0",
"husky": "^4.3.0",
2 changes: 1 addition & 1 deletion preact/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "wouter-preact",
"version": "2.8.0",
"version": "2.8.1",
"description": "A minimalistic routing for React and Preact (Preact-only version).",
"type": "module",
"files": [
12 changes: 4 additions & 8 deletions preact/types/matcher.d.ts
Original file line number Diff line number Diff line change
@@ -5,18 +5,14 @@
import { Path } from "./use-location";

export interface DefaultParams {
[paramName: string]: string;
readonly [paramName: string]: string | undefined;
}

export type Params<T extends DefaultParams = DefaultParams> = T;

export type MatchWithParams<T extends DefaultParams = DefaultParams> = [
true,
Params<T>
];
export type MatchWithParams<T extends DefaultParams = DefaultParams> = [true, Params<T>];
export type NoMatch = [false, null];
export type Match<T extends DefaultParams = DefaultParams> =
| MatchWithParams<T>
| NoMatch;
export type Match<T extends DefaultParams = DefaultParams> = MatchWithParams<T> | NoMatch;

export type MatcherFn = (pattern: Path, path: Path) => Match;

74 changes: 28 additions & 46 deletions preact/types/ts4.1/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
// Minimum TypeScript Version: 4.1
// tslint:disable:no-unnecessary-generics

import {
JSX,
FunctionComponent,
ComponentType,
ComponentChildren,
VNode,
} from "preact";
import { JSX, FunctionComponent, ComponentType, ComponentChildren, VNode } from "preact";

import {
Path,
@@ -17,34 +11,31 @@ import {
LocationHook,
} from "../use-location";

import { DefaultParams, Params, Match, MatcherFn } from "../matcher";
import { DefaultParams, Match, MatcherFn } from "../matcher";

// re-export types from these modules
export * from "../matcher";
export * from "../use-location";

export type ExtractRouteOptionalParam<PathType extends Path> =
PathType extends `${infer Param}?`
? { [k in Param]: string | undefined }
: PathType extends `${infer Param}*`
? { [k in Param]: string | undefined }
: PathType extends `${infer Param}+`
? { [k in Param]: string }
: { [k in PathType]: string };

export type ExtractRouteParams<PathType extends string> =
string extends PathType
? { [k in string]: string }
: PathType extends `${infer _Start}:${infer ParamWithOptionalRegExp}/${infer Rest}`
? ParamWithOptionalRegExp extends `${infer Param}(${infer _RegExp})`
? ExtractRouteOptionalParam<Param> & ExtractRouteParams<Rest>
: ExtractRouteOptionalParam<ParamWithOptionalRegExp> &
ExtractRouteParams<Rest>
: PathType extends `${infer _Start}:${infer ParamWithOptionalRegExp}`
? ParamWithOptionalRegExp extends `${infer Param}(${infer _RegExp})`
? ExtractRouteOptionalParam<Param>
: ExtractRouteOptionalParam<ParamWithOptionalRegExp>
: {};
export type ExtractRouteOptionalParam<PathType extends Path> = PathType extends `${infer Param}?`
? { readonly [k in Param]: string | undefined }
: PathType extends `${infer Param}*`
? { readonly [k in Param]: string | undefined }
: PathType extends `${infer Param}+`
? { readonly [k in Param]: string }
: { readonly [k in PathType]: string };

export type ExtractRouteParams<PathType extends string> = string extends PathType
? DefaultParams
: PathType extends `${infer _Start}:${infer ParamWithOptionalRegExp}/${infer Rest}`
? ParamWithOptionalRegExp extends `${infer Param}(${infer _RegExp})`
? ExtractRouteOptionalParam<Param> & ExtractRouteParams<Rest>
: ExtractRouteOptionalParam<ParamWithOptionalRegExp> & ExtractRouteParams<Rest>
: PathType extends `${infer _Start}:${infer ParamWithOptionalRegExp}`
? ParamWithOptionalRegExp extends `${infer Param}(${infer _RegExp})`
? ExtractRouteOptionalParam<Param>
: ExtractRouteOptionalParam<ParamWithOptionalRegExp>
: {};

/*
* Components: <Route />
@@ -59,15 +50,11 @@ export interface RouteProps<
RoutePath extends Path = Path
> {
children?:
| ((
params: T extends DefaultParams ? T : ExtractRouteParams<RoutePath>
) => ComponentChildren)
| ((params: T extends DefaultParams ? T : ExtractRouteParams<RoutePath>) => ComponentChildren)
| ComponentChildren;
path?: RoutePath;
component?: ComponentType<
RouteComponentProps<
T extends DefaultParams ? T : ExtractRouteParams<RoutePath>
>
RouteComponentProps<T extends DefaultParams ? T : ExtractRouteParams<RoutePath>>
>;
}

@@ -92,10 +79,9 @@ export type LinkProps<H extends BaseLocationHook = LocationHook> = Omit<
> &
NavigationalProps<H>;

export type RedirectProps<H extends BaseLocationHook = LocationHook> =
NavigationalProps<H> & {
children?: never;
};
export type RedirectProps<H extends BaseLocationHook = LocationHook> = NavigationalProps<H> & {
children?: never;
};

export function Link<H extends BaseLocationHook = LocationHook>(
props: LinkProps<H>
@@ -138,12 +124,8 @@ export function useRouter(): RouterProps;
export function useRoute<
T extends DefaultParams | undefined = undefined,
RoutePath extends Path = Path
>(
pattern: RoutePath
): Match<T extends DefaultParams ? T : ExtractRouteParams<RoutePath>>;
>(pattern: RoutePath): Match<T extends DefaultParams ? T : ExtractRouteParams<RoutePath>>;

export function useLocation<
H extends BaseLocationHook = LocationHook
>(): HookReturnValue<H>;
export function useLocation<H extends BaseLocationHook = LocationHook>(): HookReturnValue<H>;

// tslint:enable:no-unnecessary-generics
29 changes: 13 additions & 16 deletions preact/types/ts4.1/type-specs.tsx
Original file line number Diff line number Diff line change
@@ -60,19 +60,13 @@ const invalidParamsWithGeneric: Params<{ id: number }> = { id: 13 }; // $ExpectE
This is a <b>mixed</b> content
</Route>;

<Route path="/users/:id">
{(params: Params): React.ReactNode => `User id: ${params.id}`}
</Route>;
<Route path="/users/:id">{(params: Params): React.ReactNode => `User id: ${params.id}`}</Route>;

<Route path="/users/:id">{({ id }) => `User id: ${id}`}</Route>;

<Route path="/users/:id">
{({ age }) => `User age: ${age}`} // $ExpectError
</Route>;
<Route path="/users/:id">{({ age }) => `User age: ${age}`}</Route>; // $ExpectError

<Route path="/users/:id">
{({ age }: { age: string }) => `User age: ${age}`}
</Route>;
<Route path="/users/:id">{({ age }: { age: string }) => `User age: ${age}`}</Route>;

<Route path="/app" match={true} />; // $ExpectError

@@ -85,9 +79,7 @@ const invalidParamsWithGeneric: Params<{ id: number }> = { id: 13 }; // $ExpectE
</Route>;

// infer only named params
<Route path="/:first/:second">
{({ first, second }) => `first: ${first}, second: ${second}`}
</Route>;
<Route path="/:first/:second">{({ first, second }) => `first: ${first}, second: ${second}`}</Route>;

// for pathToRegexp matcher
<Route path="/:user([a-z]i+)/profile/:tab/:first+/:second*">
@@ -100,6 +92,14 @@ const invalidParamsWithGeneric: Params<{ id: number }> = { id: 13 }; // $ExpectE
}}
</Route>;

<Route path={JSON.parse('"/home"')}>
{({ itemId }) => {
const fn = (a: string) => `noop ${a}`;
fn(itemId); // $ExpectError
return <div className={itemId} />;
}}
</Route>;

/*
* Link and Redirect component type specs
*/
@@ -150,10 +150,7 @@ const invalidParamsWithGeneric: Params<{ id: number }> = { id: 13 }; // $ExpectE

Redirect<UseNetworkLocation>({ href: "/home", delay: 1000 });
// example custom hook
type UseLocWithNoOptions = () => [
string,
(to: string, foo: number, bar: string) => void
];
type UseLocWithNoOptions = () => [string, (to: string, foo: number, bar: string) => void];
Redirect<UseLocWithNoOptions>({ href: "/app" });

<Redirect>something</Redirect>; // $ExpectError
12 changes: 4 additions & 8 deletions types/matcher.d.ts
Original file line number Diff line number Diff line change
@@ -5,18 +5,14 @@
import { Path } from "./use-location";

export interface DefaultParams {
[paramName: string]: string;
readonly [paramName: string]: string | undefined;
}

export type Params<T extends DefaultParams = DefaultParams> = T;

export type MatchWithParams<T extends DefaultParams = DefaultParams> = [
true,
Params<T>
];
export type MatchWithParams<T extends DefaultParams = DefaultParams> = [true, Params<T>];
export type NoMatch = [false, null];
export type Match<T extends DefaultParams = DefaultParams> =
| MatchWithParams<T>
| NoMatch;
export type Match<T extends DefaultParams = DefaultParams> = MatchWithParams<T> | NoMatch;

export type MatcherFn = (pattern: Path, path: Path) => Match;

25 changes: 13 additions & 12 deletions types/ts3.9.4/index.d.ts
Original file line number Diff line number Diff line change
@@ -6,7 +6,8 @@ import {
PropsWithChildren,
ComponentType,
ReactElement,
ReactNode,
ReactChild,
ReactPortal,
} from "react";

import {
@@ -23,6 +24,11 @@ import { DefaultParams, Params, Match, MatcherFn } from "../matcher";
export * from "../matcher";
export * from "../use-location";

// React <18 only: fixes incorrect `ReactNode` declaration that had `{}` in the union.
// This issue has been fixed in React 18 type declaration.
// https://github.com/DefinitelyTyped/DefinitelyTyped/pull/56210
type ReactNode = ReactChild | Iterable<ReactNode> | ReactPortal | boolean | null | undefined;

/*
* Components: <Route />
*/
@@ -57,10 +63,9 @@ export type LinkProps<H extends BaseLocationHook = LocationHook> = Omit<
> &
NavigationalProps<H>;

export type RedirectProps<H extends BaseLocationHook = LocationHook> =
NavigationalProps<H> & {
children?: never;
};
export type RedirectProps<H extends BaseLocationHook = LocationHook> = NavigationalProps<H> & {
children?: never;
};

export function Redirect<H extends BaseLocationHook = LocationHook>(
props: PropsWithChildren<RedirectProps<H>>,
@@ -78,7 +83,7 @@ export function Link<H extends BaseLocationHook = LocationHook>(

export interface SwitchProps {
location?: string;
children: Array<ReactElement<RouteProps>>;
children: ReactNode;
}
export const Switch: FunctionComponent<SwitchProps>;

@@ -103,12 +108,8 @@ export const Router: FunctionComponent<

export function useRouter(): RouterProps;

export function useRoute<T extends DefaultParams = DefaultParams>(
pattern: Path
): Match<T>;
export function useRoute<T extends DefaultParams = DefaultParams>(pattern: Path): Match<T>;

export function useLocation<
H extends BaseLocationHook = LocationHook
>(): HookReturnValue<H>;
export function useLocation<H extends BaseLocationHook = LocationHook>(): HookReturnValue<H>;

// tslint:enable:no-unnecessary-generics
28 changes: 18 additions & 10 deletions types/ts3.9.4/type-specs.tsx
Original file line number Diff line number Diff line change
@@ -62,15 +62,11 @@ const invalidParamsWithGeneric: Params<{ id: number }> = { id: 13 }; // $ExpectE
This is a <b>mixed</b> content
</Route>;

<Route path="/users/:id">
{(params: Params): React.ReactNode => `User id: ${params.id}`}
</Route>;
<Route path="/users/:id">{(params: Params) => `User id: ${params.id}`}</Route>;

<Route<{ id: string }> path="/users/:id">{({ id }) => `User id: ${id}`}</Route>;

<Route<{ id: string }> path="/users/:id">
{({ age }) => `User age: ${age}`} // $ExpectError
</Route>;
<Route<{ id: string }> path="/users/:id">{({ age }) => `User age: ${age}`}</Route>; // $ExpectError

<Route path="/app" match={true} />; // $ExpectError

@@ -128,10 +124,7 @@ const invalidParamsWithGeneric: Params<{ id: number }> = { id: 13 }; // $ExpectE

Redirect<UseNetworkLocation>({ href: "/home", delay: 1000 });
// example custom hook
type UseLocWithNoOptions = () => [
string,
(to: string, foo: number, bar: string) => void
];
type UseLocWithNoOptions = () => [string, (to: string, foo: number, bar: string) => void];
Redirect<UseLocWithNoOptions>({ href: "/app" });

<Redirect>something</Redirect>; // $ExpectError
@@ -150,6 +143,21 @@ Redirect<UseLocWithNoOptions>({ href: "/app" });
<Route />
</Switch>;

<Switch>
This won't be rendered, but it's allowed
<Route path="/app/users" />
<>
<div />
I'm a fragment
</>
{false && <a>Conditionals</a>}
{null}
{undefined}
<Route />
</Switch>;

<Switch />; // $ExpectError

/*
* Router specs
*/
Loading