TypeScript 中的嵌套递归类型提示?

Nested recursive Type Hinting in TypeScript?

我不太确定我说的对不对,所以我会解释一下。

我正在使用 TypeScript 创建 React 应用程序,为了让我的生活更简单,我想将所有路由路径分别存储为常量,我还希望在 VS Code 中拥有像自动完成一样的 TypeScript。所以我有这个结构之王:

type GlobalRoutingT = 'user' | 'listing';

type RoutingVariants = {
  list: string,
  add: string,
  get: string,
  [key: string]: RoutingVariants | string,
};

type RouterT = Record<GlobalRoutingT, RoutingVariants>;

export const Routes: RouterT = {
  user: {
    list: '/user',
    add: '/user/add',
    get: '/user/:id',
    invoices: {
      list: '/user/invoices',
      add: '/user/invoices/add',
      get: '/user/invoices/:id',
    }
  },
  listing: {
    list: '/listing',
    add: '/listing/add',
    get: '/listing/:id',
  },
};

效果很好我现在可以这样用

<Route path={Routes.user.invoices.get} exact >
  <GetInvoice />
</Route>

但在 VS Code 中出现错误:

Property 'get' does not exist on type 'string | RoutingVariants'. Property 'get' does not exist on type 'string'.

和 Routes.user.invoices.get部分被高亮.

我做错了什么?

你需要强制类型转换,试试这个:

<Route path={(Routes.user.invoices as RoutingVariants).get} exact >
  <GetInvoice />
</Route>

您想要的似乎不太可能:

您不能在同一接口/类型上将索引签名与命名键结合使用。

作为解决方法,您可以使用“子”属性,像这样:

type GlobalRoutingT = 'user' | 'listing';

type RoutingVariants = {
    list: string,
    add: string,
    get: string,
    child?: Record<string, RoutingVariants>
};

type RouterT = Record<GlobalRoutingT, RoutingVariants>;

export const Routes: RouterT = {
    user: {
        list: '/user',
        add: '/user/add',
        get: '/user/:id',
        child: {
            invoices: {
                list: '/user/invoices',
                add: '/user/invoices/add',
                get: '/user/invoices/:id'
            }
        }
    },
    listing: {
        list: '/listing',
        add: '/listing/add',
        get: '/listing/:id'
    }
};

const a = Routes.user.child?.invoices.get;

请注意我必须如何使用 ?. 来访问子项,因为它在类型定义中是可选的。

您可以将 child 替换为更短的字母,$_...