-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proper way to access routes types from vanilla TS code? #52
Comments
It's a pretty complex question. First of all, there are three kinds of types here:
Getting original typesThe intended way is to decouple the typing, as you did in the second example: const steps = ["account", "additional-info", "verify"] as const;
export type Step = (typeof steps)[number];
export const ROUTES = {
SIGN_UP: route("sign-up", {
searchParams: {
step: union(steps),
},
}),
}; Specifically for string unions, I find enums more suitable here. I know they're frowned upon, but the only downside when used like this is that the type is effectively branded (which may actually be desired). export enum Step {
ACCOUNT = "account",
ADDITIONAL_INFO = "additional-info",
VERIFY = "verify",
}
export const ROUTES = {
SIGN_UP: route("sign-up", {
searchParams: {
step: union(Object.values(Step)),
},
}),
}; As for extracting these types from the route object, well... it's quite tricky and requires a somewhat complex custom helper. I don't have time to write a comprehensive one right now, but here is a draft that handles search params: type Test = ExtractOriginalTypes<typeof ROUTES.SIGN_UP, "search">["step"];
type ExtractOriginalTypes<TRoute, TKind extends "search", TMode extends "out" | "in" = "out"> = TRoute extends Route<
infer TPath,
infer TPathParams,
infer TSearchParams,
infer THash,
infer TState
>
? ExtractOriginalSearchTypes<TSearchParams, TMode>
: never;
type ExtractOriginalSearchTypes<TSearchParams, TMode extends "out" | "in" = "out"> = {
[TKey in keyof TSearchParams]: ExtractSearchType<TSearchParams[TKey], TMode>;
};
type ExtractSearchType<TType, TMode extends "out" | "in"> = TType extends SearchParamType<infer TOut, infer TIn>
? TMode extends "out"
? TOut
: TIn
: never;
Getting input / output params typesIn your workaround, you get an output param type (which actually should include type ExtractOutParams<TRoute, TKind extends "pathname" | "search" | "hash" | "state"> = TRoute extends Route<
infer TPath,
infer TPathTypes,
infer TSearchTypes,
infer THash,
infer TState
>
? TKind extends "pathname"
? OutParams<TPath, TPathTypes>
: TKind extends "search"
? OutSearchParams<TSearchTypes>
: TKind extends "hash"
? THash[number] | undefined
: OutStateParams<TState>
: never;
type ExtractInParams<TRoute, TKind extends "pathname" | "search" | "hash" | "state"> = TRoute extends Route<
infer TPath,
infer TPathTypes,
infer TSearchTypes,
infer THash,
infer TState
>
? TKind extends "pathname"
? InParams<TPath, TPathTypes>
: TKind extends "search"
? InSearchParams<TSearchTypes>
: TKind extends "hash"
? THash[number] | undefined
: InStateParams<TState>
: never; |
I realised that it's not immediately obvious: the only difference between original types and input/output route params types is that |
Is there a direct way to extract the type of route data (e.g. search params) from the ROUTES object? I couldn't find it after reading the documentation.
However, I did find a workaround:
It's just a matter of preference, I'd like to work this way. I could also decouple the route typing from the ROUTES object, like
The text was updated successfully, but these errors were encountered: