Last active
October 4, 2022 00:36
-
-
Save swyxio/37a6a3d248c2d4031801f0d568904df8 to your computer and use it in GitHub Desktop.
react router dom v6 types - i have not tested this in all cases, nor have i ensured this covers the full api, - this should just be a nice drop in single .d.ts file that covers basic usecases detailed in https://dev.to/emreloper/react-router-v6-in-two-minutes-2i96, including inlining the necessary types for history and react-router
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// // with thanks | |
// https://dev.to/emreloper/react-router-v6-in-two-minutes-2i96 | |
// https://github.com/ReactTraining/react-router/blob/dev/docs/installation/getting-started.md | |
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/9d29adedf662de685356f711951ef8b9e8342865/types/react-router/index.d.ts#L1 | |
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/9d29adedf662de685356f711951ef8b9e8342865/types/react-router-dom/index.d.ts#L1 | |
// // release notes | |
// https://github.com/ReactTraining/react-router/releases/tag/v6.0.0-alpha.3 | |
declare module "react-router-dom" { | |
import * as React from 'react'; | |
/** | |
* react-router-dom | |
*/ | |
// new in v6 | |
type navigateFn<T> = (to: string | number, options?: NavigateOptions<T>) => void | |
export function useNavigate<T = Record<string, any>> (to: string | number, options?: Omit<NavigateProps<T>, 'to'>): navigateFn<T>; | |
type NavigateOptions<T> = Omit<NavigateProps<T>, 'to'> | |
type NavigateProps<T> = { | |
to: string | number, | |
replace?: boolean, | |
state?: T | |
} | |
export class Navigate<T = any> extends React.Component<NavigateProps<T>>{} | |
// existing api's | |
export interface BrowserRouterProps { | |
basename?: string; | |
getUserConfirmation?: ( | |
message: string, | |
callback: (ok: boolean) => void | |
) => void; | |
forceRefresh?: boolean; | |
keyLength?: number; | |
} | |
export class BrowserRouter extends React.Component<BrowserRouterProps, any> {} | |
export interface StaticContext { | |
statusCode?: number; | |
} | |
export interface NavLinkProps<S = H.LocationState> extends LinkProps<S> { | |
activeClassName?: string; | |
activeStyle?: React.CSSProperties; | |
exact?: boolean; | |
strict?: boolean; | |
isActive?<Params extends { [K in keyof Params]?: string }>( | |
match: match<Params>, | |
location: H.Location<S> | |
): boolean; | |
location?: H.Location<S>; | |
} | |
export class NavLink<S = H.LocationState> extends React.Component< | |
NavLinkProps<S>, | |
any | |
> {} | |
export interface LinkProps<S = H.LocationState> extends React.AnchorHTMLAttributes<HTMLAnchorElement> { | |
component?: React.ComponentType<any>; | |
to: H.LocationDescriptor<S> | ((location: H.Location<S>) => H.LocationDescriptor<S>); | |
replace?: boolean; | |
innerRef?: React.Ref<HTMLAnchorElement>; | |
} | |
export class Link<S = H.LocationState> extends React.Component< | |
LinkProps<S>, | |
any | |
> {} | |
// new in v6 | |
export class Outlet extends React.Component { | |
props: {}; // denying props or children! | |
} | |
/** | |
* history | |
*/ | |
export namespace H { | |
export type Action = 'PUSH' | 'POP' | 'REPLACE'; | |
export type UnregisterCallback = () => void; | |
export interface History<HistoryLocationState = LocationState> { | |
length: number; | |
action: Action; | |
location: Location<HistoryLocationState>; | |
push(path: Path, state?: HistoryLocationState): void; | |
push(location: LocationDescriptorObject<HistoryLocationState>): void; | |
replace(path: Path, state?: HistoryLocationState): void; | |
replace(location: LocationDescriptorObject<HistoryLocationState>): void; | |
go(n: number): void; | |
goBack(): void; | |
goForward(): void; | |
block( | |
prompt?: boolean | string | TransitionPromptHook<HistoryLocationState>, | |
): UnregisterCallback; | |
listen(listener: LocationListener<HistoryLocationState>): UnregisterCallback; | |
createHref(location: LocationDescriptorObject<HistoryLocationState>): Href; | |
} | |
export type Location<S = LocationState> = { | |
pathname: Pathname; | |
search: Search; | |
state: S; | |
hash: Hash; | |
key?: LocationKey; | |
} | |
export interface LocationDescriptorObject<S = LocationState> { | |
pathname?: Pathname; | |
search?: Search; | |
state?: S; | |
hash?: Hash; | |
key?: LocationKey; | |
} | |
export namespace History { | |
export type LocationDescriptor<S = LocationState> = Path | LocationDescriptorObject<S>; | |
export type LocationKey = string; | |
export type LocationListener<S = LocationState> = ( | |
location: Location<S>, | |
action: Action, | |
) => void; | |
// The value type here is a "poor man's `unknown`". When these types support TypeScript | |
// 3.0+, we can replace this with `unknown`. | |
type PoorMansUnknown = {} | null | undefined; | |
export type LocationState = PoorMansUnknown; | |
export type Path = string; | |
export type Pathname = string; | |
export type Search = string; | |
export type TransitionHook<S = LocationState> = ( | |
location: Location<S>, | |
callback: (result: any) => void, | |
) => any; | |
export type TransitionPromptHook<S = LocationState> = ( | |
location: Location<S>, | |
action: Action, | |
) => string | false | void; | |
export type Hash = string; | |
export type Href = string; | |
} | |
export type LocationDescriptor<S = LocationState> = History.LocationDescriptor<S>; | |
export type LocationKey = History.LocationKey; | |
export type LocationListener<S = LocationState> = History.LocationListener<S>; | |
export type LocationState = History.LocationState; | |
export type Path = History.Path; | |
export type Pathname = History.Pathname; | |
export type Search = History.Search; | |
export type TransitionHook<S = LocationState> = History.TransitionHook<S>; | |
export type TransitionPromptHook< | |
S = LocationState | |
> = History.TransitionPromptHook<S>; | |
export type Hash = History.Hash; | |
export type Href = History.Href; | |
} | |
/** | |
* react-router | |
*/ | |
// new in v6 | |
export function useRoutes(routeArray: RouteProps[]): Routes | |
export function useSearchParams(): URLSearchParams | |
// used to be SwitchProps | |
export interface RoutesProps { | |
children?: React.ReactNode; | |
location?: H.Location; | |
} | |
// used to be Switch | |
export class Routes extends React.Component<RoutesProps, any> {} | |
export interface RouteComponentProps< | |
Params extends { [K in keyof Params]?: string } = {}, | |
C extends StaticContext = StaticContext, | |
S = H.LocationState | |
> { | |
history: H.History<S>; | |
location: H.Location<S>; | |
match: match<Params>; | |
staticContext?: C; | |
} | |
export interface match<Params extends { [K in keyof Params]?: string } = {}> { | |
params: Params; | |
isExact: boolean; | |
path: string; | |
url: string; | |
} | |
export interface RouteProps { | |
location?: H.Location; | |
element?: React.ReactNode; // SWYX: shortcut; have to do see if we can do better | |
render?: (props: RouteComponentProps<any>) => React.ReactNode; | |
children?: | |
// | ((props: RouteChildrenProps<any>) => React.ReactNode) // SWYX: i think this is not needed anymore? | |
| RouteProps[] // new in v6 | |
| React.ReactNode; | |
path?: string | string[]; | |
sensitive?: boolean; | |
// // no more in v6 | |
// component?: | |
// | React.ComponentType<RouteComponentProps<any>> | |
// | React.ComponentType<any>; | |
// exact?: boolean; | |
// strict?: boolean; | |
} | |
export class Route<T extends RouteProps = RouteProps> extends React.Component< | |
T, | |
any | |
> {} | |
} |
not sure why passing T = Object as a prop to useNavigate (I'm not familiar with such pattern)
that was a typo. I meant to write useNavigate<T = Object>
instead - basically saying i declare a generic type T
, and if the user doesnt give me anything, i'll just give it a default of Object
.
ok i hear you - thats good enough for me to work with. i'll fix it up, cheers
thank you! really appreciate your work here and in other projects 👍 I'm happy if I can help in any way
there is finally an attempt to update types on definitelytyped - see @murbanowicz's work here DefinitelyTyped/DefinitelyTyped#44015
i dont intend to maintain typings here much longer as i dont currently actively use RR
I will appreciate any help with moving it forward! @gitpash
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Was looking at it more closely
not sure why passing
T = Object
as a prop touseNavigate
(I'm not familiar with such pattern)in my perspective main reason is to explicitly describe the shape of
state
prop inNavigateProps
, if soexport function useNavigate<T>(): (to: string | number, options?: Omit<NavigateProps<T>, 'to'>) => navigateFn;
- should be enoughbut for more accuracy in order to define
object
like shape (to prevent smth likeuseNavigate<string>
) we can useMetaobject
this seems to be ok in my project