(Esta es una pregunta para comprender el funcionamiento, no una pregunta de "¿cómo puedo...")
Cuando trabajo con React Router, me di cuenta de que Vscode IntelliSense puede sugerirme parámetros fuertemente tipados cuando los escribo en una ruta como esta:
<Route path='/users/:userId?' render={props => <UserManager selectedId={props.}/>} />
Cuando props.match.params.
, cada vez que tengo una cadena de path
como :text
va como un parámetro fuertemente tipado desde el interior de la cadena a los parámetros como una propiedad fuertemente tipada (y un parámetro opcional si hay un signo de interrogación como en mi caso):
¿Cómo puede Vscode/TypeScript/React Router generar un argumento fuertemente tipado a partir de una cadena simple ingresada por el usuario?
Consulte esta pregunta solo como referencia.
Encontrarás una explicación en los comentarios:
import React from 'react' type PathParams< Path extends string > = /** * Check whether provided argument is valid route string with parameters */ (Path extends `:${infer Param}/${infer Rest}` /** * If yes, call PathParams recursively with rest part of the string * and make it union with current param */ ? Param | PathParams<Rest> /** * Otherwise, check if argument is standalone parameter, for instance ":userId" */ : (Path extends `:${infer Param}` /** * If yes, return it */ ? Param /** * Otherwise check if provided string is allowed route string * but without /, for instance "user:userId" */ : (Path extends `${infer _Prefix}:${infer Rest}` /** * If yes, call recursively PathParams with this parameter */ ? PathParams<`:${Rest}`> /** * If provided string is invalid - return never */ : never) ) ) /** * As you might have noticed, we ended up * with union of strings. Now we just need to convert this union * into record. It is the easiest part */ type Params = PathParams<":siteId/user/:userId"> /** * Convert union to record with appropriate keys */ type PathArgs<Path extends string> = { [K in PathParams<Path>]: string }; // type Result = { // siteId: string; // userId: string; // } type Result = PathArgs<"/dashboard/:siteId/user:userId">
Ahora intentemos construir un componente de reacción similar:
type Props<Path extends string> = { path: Path, params: PathArgs<Path> } const Route = <Path extends string>(props: Props<Path>) => { return null } const jsx = <Route path="/dashboard/:siteId/user:userId" params={{ siteId: 'hello', userId: 'world' }} /> // ok const jsx_ = <Route path="/dashboard/:siteId/user:userId" params={{ siteId: 'hello' }} /> // error, missing userId prop
Este ejemplo debería darle una pista de cómo se hace en el enrutador de reacción. Sé que mi ejemplo no refleja el mismo comportamiento al 100%, pero creo que es útil
Tenga en cuenta que mi ejemplo es mucho más pequeño que la implementación real.
Implementación original que puede encontrar aquí con comentarios. Su implementación es mucho mayor porque puede haber muchos casos extremos.