有没有一种方法可以根据打字稿中修改的属性来描述代理的类型

Is there a way to describe type for Proxy based on modified properties in typescript

我有一个路线列表:

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',
  
  ...
}

和一个 Proxy 可以处理方法的对象:

即getRouteAUrl, getRouteBUrl 等等.

问题是:

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

像这样

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) {
    ...
  }
});

是的,您可以在 mapped type 中使用 as 子句,通过它可以指定生成的 属性 名称的转换:

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


或者更简单:

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