Stack Exchange
Is there a way to describe type for Proxy based on modified properties in typescript
I have a list of routes:


export interface RouteMap {
  routeA: string;
  routeB: string;
  routeC: string;
  ...
}

const routesMap: RouteMap = {
  routeA: 'route-a-url',
  routeB: 'route-b-url/:param',
  routeC: 'route-c-url/:some-id/data',
  
  ...
}



and a Proxy to object that could handle methods:

getRouteNameUrl(...arg: any[]): string;
goToRouteNameUrl(...arg: any[]): void;
probably some other dynamic boilerplate stuff

i.e. getRouteAUrl, getRouteBUrl and so on.
the question is:

Is there a way to describe the Proxed object, that is based on some interface/class type's modified properties in typescript?

something like this


type ProxedRouteMap<T> = {
  [get`[P in keyof T]`Url]: (...arg: string[]) => string;
  [goTo`[P in keyof T]`]: (...arg: string[]) => void;
  ...
}

const routeMapService: ProxedRouteMap<RouteMap> = new Proxy(routeMap, {
  apply(target, thisArg, ...args) {
    ...
  }
});




Does this approach meet your needs? If so I can write up an answer; if not, please explain any unsatisfied use cases.

@jcalz thank you, that is really very nice solution and probably should be added as answer too.

Yes, you can use as clause in mapped type through which a transformation of the generated property names can be specified:
type ProxedRouteMap<T> = {
  [P in keyof T as `get${Capitalize<string & P>}Url`]: (...arg: string[]) => string;
} & {
  [P in keyof T as `goTo${Capitalize<string & P>}`]: (...arg: string[]) => void;
}

/**
 * {
 *  getRouteAUrl: (...arg: string[]) => string;
 *  getRouteBUrl: (...arg: string[]) => string;
 *  getRouteCUrl: (...arg: string[]) => string;
 * } & {
 *  goToRouteA: (...arg: string[]) => void;
 *  goToRouteB: (...arg: string[]) => void;
 *  goToRouteC: (...arg: string[]) => void;
 * } 
 */
type Foo = ProxedRouteMap<RouteMap>

Playground

Or even simpler:
type ProxedRouteMap<T> = {
  [P in `get${Capitalize<keyof T & string>}Url`]: (...arg: string[]) => string;
} & {
    [P in `goTo${Capitalize<keyof T & string>}`]: (...arg: string[]) => void;
  }

