typescript 从路径字符串推断路由参数名称,例如'/posts/:id'

k2fxgqgv  于 2023-05-08  发布在  TypeScript
关注(0)|答案(2)|浏览(173)

我有一个Route接口,它包含一个params对象,我想在那个params对象上获得类型安全,这样,例如:
给定路由配置:

{
  post: {
    path: 'posts/:id',
  }
}
navigtate({ name: 'post', params: { wrongKey: '1' } });

我正在为Route使用这个接口,但是T[keyof T]显然无法推断它是哪个键。

type Route<T extends Config> = {
  hash?: string;
  name: keyof T & string;
  params?: RouteParams<T[keyof T]['path']>;
  search?: Record<string, string>;
};

我希望这个错误,因为wrongKey不是id。目前,我所能做的就是将参数键作为string的类型。
完整的代码在这里的操场链接。

ux6nzvsh

ux6nzvsh1#

首先,你缺少了as const来使你的路径成为文字,而不仅仅是string

const routes = {
  post: { path: '/posts/:id' },
  blah: { path: '/posts/:blah' },
} as const;

其次,navigate需要第二个泛型参数,这样parameters就不会被推断为所有可能参数的并集:

type Route<T extends Config, K extends keyof T = keyof T> = {
  hash?: string;
  name: K;
  params?: RouteParams<T[K]['path']>;
  search?: Record<string, string>;
};

const routes = {
  post: { path: '/posts/:id' },
  blah: { path: '/posts/:blah' },
} as const;

navigate(routes, { name: 'post', params: { id: '1' } }); //  ok
navigate(routes, { name: 'post', params: {} }); //           errors: missing id
navigate(routes, { name: 'postj', params: { id: '1' } }); // errors: no postj
navigate(routes, { name: 'post', params: { idj: '1' } }); // errors: no idj

function navigate<T extends Config, K extends keyof T>(config: T, route: Route<T, K>) { }

https://tsplay.dev/NB8nbW

nom7f22z

nom7f22z2#

看看这个HOTScript library。最后一个示例(就在API部分之前)做了类似的事情。你可以做一些编辑,使它成为你喜欢的方式。
或者尝试在routes对象后面添加as const,如下所示:

const routes = {
  post: { path: '/posts/:id' },
} as const;

这将把path属性作为文字类型,而不仅仅是string类型。

相关问题