首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >hookrouter中路由映射对象的Typescript类型是什么?

hookrouter中路由映射对象的Typescript类型是什么?
EN

Stack Overflow用户
提问于 2021-03-10 04:04:56
回答 1查看 222关注 0票数 0

如何替换任何钩子路由器??

代码语言:javascript
复制
type RouteMap = Record<string, (props?: any) => JSX.Element>;
                                        ^^^

完整代码

代码语言:javascript
复制
import {
  useRoutes,
  usePath,
} from 'hookrouter'

//// HOW DO I REPLACE any???
type RouteMap = Record<string, (props?: any) => JSX.Element>;

const routes: RouteMap = {
  '/': () => <LandingPage />,
  '/asdf': () => <ASDF />,
  '/list/:userId': ({ id }) => <MainPage userId={id} />,
};

function MainApp(): JSX.Element | null {
  const routeResult = useRoutes(routes);
  const userProfile = useUserProfileState();
...
...
EN

回答 1

Stack Overflow用户

发布于 2021-03-28 05:08:50

definitions for this package是非常宽松的。它们将道具描述为{[key: string]: any;},并允许您的路由渲染函数返回任何内容。

Record<string, string>更严格了一步。这将在模糊的意义上描述道具,因为URL段始终是string

这比any更好,但它不能反映每个组件都有不同的属性这一事实。

实际上你当前的代码中有一个错误,如果我们能让Typescript来发现这一点,那就太好了。

代码语言:javascript
复制
'/list/:userId': ({ id }) => <MainPage userId={id} />

因为URL参数是userId,所以道具得到的是userId 而不是 id

我们可以使用新的Typescript模板文字类型来实现非常严格的类型。我们可以创建一个ExtractSlugs实用程序类型来查找路由字符串中的所有段塞。

代码语言:javascript
复制
type ExtractSlugs<T extends string> = 
  // matches from : to / 
  T extends `${string}:${infer Slug}/${infer After}` ? Slug | ExtractSlugs<After> : 
  // matches from : to end
  T extends `${string}:${infer Slug}` ? Slug : 
  never;

type A = ExtractSlugs<'/list/:userId/:other'>  // type: "userId" | "other"
type B = ExtractSlugs<'/list/:userId'> // type: "userId"
type C = ExtractSlugs<'/list'> // type: never

这些应该是我们的props对象的关键字,并且值应该是string

代码语言:javascript
复制
type RouteMap<Keys extends string> = {
  [K in Keys]: (props: Record<ExtractSlugs<K>, string>) => JSX.Element | null
}

为了创建一个键依赖于值的对象,我们需要使用一个identify函数。这允许我们对所有键-值对实施限制。

代码语言:javascript
复制
const createRoutes = <Keys extends string>(map: RouteMap<Keys>) => map;

现在我们得到一个错误!“类型”Record<“userId”,string>“上不存在属性”“id”

代码语言:javascript
复制
createRoutes({
  '/list/:userId': ({ id }) => <MainPage userId={id} />,
})

但这很好:

代码语言:javascript
复制
const routes = createRoutes({
  '/': () => <LandingPage />,
  '/asdf': () => <ASDF />,
  '/list/:userId': ({ userId }) => <MainPage userId={userId} />,
})

如果你的页面是函数组件,那么你也应该能够直接传递它们。

代码语言:javascript
复制
const routes = createRoutes({
  '/': LandingPage,
  '/asdf': ASDF,
  '/list/:userId': MainPage,
})

如果您尝试对密钥中没有:userId的路由使用MainPage,则会出现错误。

Typescript Playground Link

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66553989

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档