I'm having trouble typing a callback function in TypeScript to map a parameter result. The following function is causing me some difficulty:
type CustomRouteType<TParam = any> = <T>(value?: T) => TParam;
const createRoute = <TTypes extends CustomRouteType[]>
(dictionary: RouteDictionary<TTypes>,
callback: (...params: TTypes) => void) => {
// Logic Here
}
createRoute(
route`/api/someEndpoint/${Number}/${String}/test`,
(p1, p2) => {
});
The route function converts the string literal into a custom dictionary that reveals the parameters in the route, making it impossible to determine the type returned by the route function ahead of time. In this example, the function returns a RouteDictionary<[NumberConstructor, StringConstructor]>, and therefore, the parameters p1 and p2 in the callback are instances of those constructors. I want to convert these parameters to match the ReturnValue types of those constructors.
In Typescript, there is only ReturnValue available and not ReturnValues. How can I successfully map these types so that the parameters of the callback function automatically infer the desired return types?
For further clarification:
class RouteString {
constructor(public routeString: string) { }
}
class RouteParameter<T = any> {
constructor(public routeString: CustomRouteType<T>) { }
}
type RouteDictionary<TTypes extends CustomRouteType[]> = {
routeParts: (RouteString | RouteParameter)[]
types: TTypes
}
const route = <TParams extends any[], TTypes extends CustomRouteType<any>[]>
(template: TemplateStringsArray, ...keys: TTypes): RouteDictionary<TTypes> => {
let routeParts: (RouteString | RouteParameter)[] = [];
const stringParts = template.raw || [];
for (let partIndex = 0; partIndex < stringParts.length; partIndex++) {
const part = stringParts[partIndex];
const stringChunks = part.split('/').filter(chunkPart => chunkPart !== String())
routeParts = [... routeParts, ...stringChunks.map(chunk => new RouteString(chunk))]
if (keys.length === 0) continue
if (keys.length < partIndex) continue
const routeParam = keys[partIndex]
if (!routeParam) continue
routeParts = [...routeParts, new RouteParameter(routeParam)]
}
return {
routeParts,
types: keys
};
}