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
替换为更短的字母,$
或 _
...
我不太确定我说的对不对,所以我会解释一下。
我正在使用 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
替换为更短的字母,$
或 _
...