From 498d415b56995194bececf0bb4df18414ffc01b4 Mon Sep 17 00:00:00 2001 From: Alexander Tolkunov Date: Fri, 21 Jun 2019 03:42:32 +0300 Subject: [PATCH] [Wouter] Add types for v2 (#36330) --- types/wouter/index.d.ts | 43 ++++++++------- types/wouter/matcher.d.ts | 8 +++ types/wouter/static-location.d.ts | 7 +++ types/wouter/tsconfig.json | 6 +- types/wouter/use-location.d.ts | 3 + types/wouter/v1/index.d.ts | 58 ++++++++++++++++++++ types/wouter/v1/tsconfig.json | 30 ++++++++++ types/wouter/v1/tslint.json | 1 + types/wouter/v1/wouter-tests.tsx | 78 ++++++++++++++++++++++++++ types/wouter/wouter-tests.tsx | 91 ++++++++++++++++++++----------- 10 files changed, 274 insertions(+), 51 deletions(-) create mode 100644 types/wouter/matcher.d.ts create mode 100644 types/wouter/static-location.d.ts create mode 100644 types/wouter/use-location.d.ts create mode 100644 types/wouter/v1/index.d.ts create mode 100644 types/wouter/v1/tsconfig.json create mode 100644 types/wouter/v1/tslint.json create mode 100644 types/wouter/v1/wouter-tests.tsx diff --git a/types/wouter/index.d.ts b/types/wouter/index.d.ts index 3b4bb63879..2b09c644be 100644 --- a/types/wouter/index.d.ts +++ b/types/wouter/index.d.ts @@ -1,31 +1,38 @@ -// Type definitions for wouter 1.2 +// Type definitions for wouter 2.0 // Project: https://github.com/molefrog/wouter#readme // Definitions by: Tolkunov Alexander // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.8 -import * as React from 'react'; +import { + FunctionComponent, + ComponentType, + ReactElement, + ReactNode +} from "react"; export type Params = { [paramName: string]: string } | null; export type Path = string; export type PushCallback = (to: string) => void; +export type LocationTuple = [Path, PushCallback]; export type Match = [boolean, Params]; +export type MatcherFn = (pattern: string, path: Path) => Match; export interface RouteProps { - children?: ((params: Params) => React.ReactNode) | React.ReactNode; + children?: ((params: Params) => ReactNode) | ReactNode; path: Path; - component?: React.ComponentType; + component?: ComponentType; match?: boolean; } -export const Route: React.FunctionComponent; +export const Route: FunctionComponent; export interface LinkProps { to?: string; href?: string; - children: React.ReactElement; + children: ReactElement; onClick?: () => void; } -export const Link: React.FunctionComponent; +export const Link: FunctionComponent; export interface RedirectProps { to?: string; @@ -35,24 +42,22 @@ export const Redirect: React.FunctionComponent; export interface SwitchProps { location?: string; - children: Array>; -} -export const Switch: React.FunctionComponent; - -export interface History { - path: () => Path; - push: PushCallback; - subscribe: (cb: PushCallback) => () => void; + children: Array>; } +export const Switch: FunctionComponent; export interface RouterProps { - history: History; - matcher: (pattern: string, path: Path) => Match; + hook: () => LocationTuple; + matcher: MatcherFn; } -export const Router: React.FunctionComponent>; +export const Router: FunctionComponent< + Partial & { + children: ReactElement | ReactElement[]; + } +>; export function useRouter(): RouterProps; export function useRoute(pattern: string): Match; -export function useLocation(): [Path, PushCallback]; +export function useLocation(): LocationTuple; diff --git a/types/wouter/matcher.d.ts b/types/wouter/matcher.d.ts new file mode 100644 index 0000000000..b6a18e0e16 --- /dev/null +++ b/types/wouter/matcher.d.ts @@ -0,0 +1,8 @@ +import { MatcherFn } from "./index"; + +export default function makeMatcher( + makeRegexpFn?: ( + pattern: string, + keys?: Array<{ name: string | number }> + ) => RegExp +): MatcherFn; diff --git a/types/wouter/static-location.d.ts b/types/wouter/static-location.d.ts new file mode 100644 index 0000000000..2c1def1f24 --- /dev/null +++ b/types/wouter/static-location.d.ts @@ -0,0 +1,7 @@ +import { Path } from "./index"; + +declare function staticLocationHook( + path?: Path +): () => [Path, (x: Path) => Path]; + +export = staticLocationHook; diff --git a/types/wouter/tsconfig.json b/types/wouter/tsconfig.json index c7ebddfd1b..8e6de4f551 100644 --- a/types/wouter/tsconfig.json +++ b/types/wouter/tsconfig.json @@ -16,10 +16,14 @@ "noEmit": true, "forceConsistentCasingInFileNames": true, "jsx": "react", - "strictFunctionTypes": true + "strictFunctionTypes": true, + "allowSyntheticDefaultImports": true }, "files": [ "index.d.ts", + "use-location.d.ts", + "static-location.d.ts", + "matcher.d.ts", "wouter-tests.tsx" ] } diff --git a/types/wouter/use-location.d.ts b/types/wouter/use-location.d.ts new file mode 100644 index 0000000000..6b0085b072 --- /dev/null +++ b/types/wouter/use-location.d.ts @@ -0,0 +1,3 @@ +import { LocationTuple } from "./index"; + +export default function useLocation(): LocationTuple; diff --git a/types/wouter/v1/index.d.ts b/types/wouter/v1/index.d.ts new file mode 100644 index 0000000000..3b4bb63879 --- /dev/null +++ b/types/wouter/v1/index.d.ts @@ -0,0 +1,58 @@ +// Type definitions for wouter 1.2 +// Project: https://github.com/molefrog/wouter#readme +// Definitions by: Tolkunov Alexander +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.8 + +import * as React from 'react'; + +export type Params = { [paramName: string]: string } | null; +export type Path = string; +export type PushCallback = (to: string) => void; +export type Match = [boolean, Params]; + +export interface RouteProps { + children?: ((params: Params) => React.ReactNode) | React.ReactNode; + path: Path; + component?: React.ComponentType; + match?: boolean; +} +export const Route: React.FunctionComponent; + +export interface LinkProps { + to?: string; + href?: string; + children: React.ReactElement; + onClick?: () => void; +} +export const Link: React.FunctionComponent; + +export interface RedirectProps { + to?: string; + href?: string; +} +export const Redirect: React.FunctionComponent; + +export interface SwitchProps { + location?: string; + children: Array>; +} +export const Switch: React.FunctionComponent; + +export interface History { + path: () => Path; + push: PushCallback; + subscribe: (cb: PushCallback) => () => void; +} + +export interface RouterProps { + history: History; + matcher: (pattern: string, path: Path) => Match; +} +export const Router: React.FunctionComponent>; + +export function useRouter(): RouterProps; + +export function useRoute(pattern: string): Match; + +export function useLocation(): [Path, PushCallback]; diff --git a/types/wouter/v1/tsconfig.json b/types/wouter/v1/tsconfig.json new file mode 100644 index 0000000000..29e59ac4dd --- /dev/null +++ b/types/wouter/v1/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6", + "dom" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "baseUrl": "../../", + "typeRoots": [ + "../../" + ], + "types": [], + "paths": { + "wouter": [ + "wouter/v1" + ] + }, + "noEmit": true, + "forceConsistentCasingInFileNames": true, + "jsx": "react", + "strictFunctionTypes": true + }, + "files": [ + "index.d.ts", + "wouter-tests.tsx" + ] +} diff --git a/types/wouter/v1/tslint.json b/types/wouter/v1/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/wouter/v1/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } diff --git a/types/wouter/v1/wouter-tests.tsx b/types/wouter/v1/wouter-tests.tsx new file mode 100644 index 0000000000..5bc1ed8076 --- /dev/null +++ b/types/wouter/v1/wouter-tests.tsx @@ -0,0 +1,78 @@ +import * as React from 'react'; +import { + Router, + Route, + Link, + Switch, + useRouter, + useRoute, + useLocation, + Redirect, +} from 'wouter'; + +const Inbox = () =>

Inbox

; +const BaseTest = () => ( +
+ + Profile + + + About Us + + console.log('navigated to /inbox')}> + Inbox + + + + About Us + + {(params) =>
Hello, {params && params.name}!
} +
+ +
+
+); + +const SwitchTest = () => ( + + A + B + C + +); + +const UseRouteTest = () => { + const [match, params] = useRoute('/users/:name'); + + if (!match) return null; + + return
Welcome, {params && params.name}!
; +}; + +const UseRouterTest = () => { + const {history, matcher} = useRouter(); + const [path] = useLocation(); + const [match, params] = matcher("/users/:name", path); + + if (!match) return null; + + return ( +
+
Your name is {params && params.name}
+
history.push('/orders')}>Orders
+
+ ); +}; + +const useLocationTest = () => { + const [location, navigate] = useLocation(); + + return ( +
+
Current location: {location}
+
navigate('/home')}>Home
+
+ ); +}; + +; diff --git a/types/wouter/wouter-tests.tsx b/types/wouter/wouter-tests.tsx index 5bc1ed8076..8fd54b6313 100644 --- a/types/wouter/wouter-tests.tsx +++ b/types/wouter/wouter-tests.tsx @@ -1,14 +1,19 @@ -import * as React from 'react'; +import * as React from "react"; +import * as express from "express"; +import { renderToString } from "react-dom/server"; import { Router, Route, Link, Switch, + Redirect, useRouter, useRoute, - useLocation, - Redirect, -} from 'wouter'; + Path, + Params +} from "wouter"; +import useLocation from "wouter/use-location"; +import staticLocationHook = require("wouter/static-location"); const Inbox = () =>

Inbox

; const BaseTest = () => ( @@ -19,39 +24,27 @@ const BaseTest = () => ( About Us - console.log('navigated to /inbox')}> + console.log("navigated to /inbox")}> Inbox - About Us - - {(params) =>
Hello, {params && params.name}!
} -
- + + About Us + + {params =>
Hello, {params && params.name}!
} +
+ +
); -const SwitchTest = () => ( - - A - B - C - -); - -const UseRouteTest = () => { - const [match, params] = useRoute('/users/:name'); - - if (!match) return null; - - return
Welcome, {params && params.name}!
; -}; +; const UseRouterTest = () => { - const {history, matcher} = useRouter(); - const [path] = useLocation(); + const { hook, matcher } = useRouter(); + const [path, push] = hook(); const [match, params] = matcher("/users/:name", path); if (!match) return null; @@ -59,20 +52,56 @@ const UseRouterTest = () => { return (
Your name is {params && params.name}
-
history.push('/orders')}>Orders
+
push("/orders")}>Orders
); }; +const UseRouteTest = () => { + const [match, params] = useRoute("/users/:name"); + + if (!match) return null; + + return
Welcome, {params && params.name}!
; +}; + const useLocationTest = () => { - const [location, navigate] = useLocation(); + const [location, setLocation] = useLocation(); return (
Current location: {location}
-
navigate('/home')}>Home
+
setLocation("/home")}>Home
); }; -; +/* staticLocationHook Test */ +const app = express(); +app.get("*", (req, res) => { + const html = renderToString( + + A + B + + ); + + res.status(200).send(html); +}); + +/* customMatcher Test */ +const customMatcher = (pattern: string, path: Path): [boolean, Params] => { + const reversed = path + .replace(/^\//, "") + .split("") + .reverse() + .join(""); + + return [pattern.replace(/^\//, "") === reversed, {}]; +}; + +const customMatcherTest = () => ( + + A + +);