react-router-typesafe-routes
Version:
Enhanced type safety via validation for all route params in React Router v7.
78 lines (77 loc) • 4.02 kB
TypeScript
import { Parser, ParserHint } from "./parser.js";
interface PathnameType<TOut, TIn = TOut> {
serializeParam: (originalValue: Exclude<TIn, undefined>) => string;
deserializeParam: (plainValue: string | undefined) => TOut;
}
interface SearchType<TOut, TIn = TOut> {
serializeSearchParam: (originalValue: Exclude<TIn, undefined>) => string[] | string;
deserializeSearchParam: (plainValue: string[]) => TOut;
}
interface HashType<TOut, TIn = TOut> {
serializeHash: (originalValue: Exclude<TIn, undefined>) => string;
deserializeHash: (plainValue: string) => TOut;
}
interface StateType<TOut, TIn = TOut> {
serializeState: (originalValue: Exclude<TIn, undefined>) => unknown;
deserializeState: (plainValue: unknown) => TOut;
}
type AnyType<TOut, TIn = TOut> = PathnameType<TOut, TIn> & SearchType<TOut, TIn> & StateType<TOut, TIn> & HashType<TOut, TIn>;
type ArrayType<TOut> = SearchType<TOut[]> & StateType<TOut[]>;
type Type<TOut> = DefType<TOut | undefined> & {
default: (def: Exclude<TOut, undefined>) => DefType<Exclude<TOut, undefined>>;
defined: () => DefType<Exclude<TOut, undefined>>;
};
type DefType<TOut> = AnyType<TOut, Exclude<TOut, undefined>> & {
array: () => ArrayType<Exclude<TOut, undefined>>;
};
interface Validator<T, TPrev = unknown> {
(value: TPrev): T | undefined;
}
interface ConfigureOptions {
parserFactory: (hint: ParserHint) => Parser<any, DynamicParserHint>;
}
type DynamicParserHint = Extract<ParserHint, "string" | "number" | "boolean">;
interface EnumLike {
[s: string]: string | number;
[n: number]: string;
}
declare function configure({ parserFactory }: ConfigureOptions): {
type: <T>(validator: Validator<T, unknown>, parser?: Parser<Exclude<T, undefined>, never>) => Type<T>;
string: {
(parser?: Parser<string>): Type<string>;
<T_1 extends string>(validator: Validator<T_1, string>, parser?: Parser<T_1, never> | undefined): Type<T_1>;
};
number: {
(parser?: Parser<number>): Type<number>;
<T_2 extends number>(validator: Validator<T_2, number>, parser?: Parser<T_2, never> | undefined): Type<T_2>;
};
boolean: {
(parser?: Parser<boolean>): Type<boolean>;
<T_3 extends boolean>(validator: Validator<T_3, boolean>, parser?: Parser<T_3, never> | undefined): Type<T_3>;
};
date: {
(parser?: Parser<Date>): Type<Date>;
<T_4 extends Date>(validator: Validator<T_4, Date>, parser?: Parser<T_4, never> | undefined): Type<T_4>;
};
union: {
<U extends string | number | boolean, T_5 extends readonly U[]>(values: T_5, parser?: Parser<T_5[number], DynamicParserHint> | undefined): Type<T_5[number]>;
<T_6 extends EnumLike>(values: T_6, parser?: Parser<T_6[keyof T_6], DynamicParserHint> | undefined): Type<T_6[keyof T_6]>;
};
};
declare const type: <T>(validator: Validator<T, unknown>, parser?: Parser<Exclude<T, undefined>, never>) => Type<T>, string: {
(parser?: Parser<string>): Type<string>;
<T extends string>(validator: Validator<T, string>, parser?: Parser<T, never> | undefined): Type<T>;
}, number: {
(parser?: Parser<number>): Type<number>;
<T extends number>(validator: Validator<T, number>, parser?: Parser<T, never> | undefined): Type<T>;
}, boolean: {
(parser?: Parser<boolean>): Type<boolean>;
<T extends boolean>(validator: Validator<T, boolean>, parser?: Parser<T, never> | undefined): Type<T>;
}, date: {
(parser?: Parser<Date>): Type<Date>;
<T extends Date>(validator: Validator<T, Date>, parser?: Parser<T, never> | undefined): Type<T>;
}, union: {
<U extends string | number | boolean, T extends readonly U[]>(values: T, parser?: Parser<T[number], DynamicParserHint> | undefined): Type<T[number]>;
<T_1 extends EnumLike>(values: T_1, parser?: Parser<T_1[keyof T_1], DynamicParserHint> | undefined): Type<T_1[keyof T_1]>;
};
export { configure, type, string, number, boolean, date, union, Type, Validator, PathnameType, SearchType, HashType, StateType, };