typescript - 在 TypeScript 中将递归数组/对象作为展平对象类型返回
问题描述
我正在尝试编写一个函数,该函数采用递归对象/数组,其中每个节点都有一个“名称”,以及可选的“孩子”。然后我想有一个函数,它采用这种递归结构并返回一个类型安全的对象,其中递归出现的“名称”是键,节点是值;因此,如果您尝试访问不存在的密钥,它会在编译期间为您出错。
到目前为止,我能够以这种方式识别顶级名称(名称“a”和“b”),以便flat
将其识别为Record<"a" | "b", RouteConfigItem<"a" | "b">>
.
type RouteConfigItem<Keys> = {
name: Keys;
path: string;
children?: Array<RouteConfigItem<Keys>>;
}
type RouteConfig<Keys> = RouteConfigItem<Keys>[];
function getFlat<Keys>(routeConfig: RouteConfig<Keys>): Record<Keys, RouteConfigItem<Keys>> {
// Implementation doesn't matter.
return routeConfig as Record<Keys, RouteConfigItem<Keys>>;
}
const flat = getFlat([{
name: 'a',
path: 'a',
}, {
name: 'b',
path: 'b',
children: [{
name: 'c',
path: 'c',
}]
}] as const);
但是我怎样才能让它也看到非顶级名称呢?只关心类型,而不关心 的主体中的实现getFlat()
,我希望flat
被识别为 Record<"a" | "b" | "c", RouteConfigItem<"a" | "b" | "c">>
.
顺便说一句,代码示例在我的 WebStorm 中似乎对我有用,但在 typescriptlang.org/play 中似乎不起作用,所以我没有包含这样的链接。
解决方案
我已经简化了一点RouteConfig
定义:
type RouteConfig = {
name: string,
path: string,
children?: ReadonlyArray<RouteConfig>
};
现在要提取密钥,您可以:
type ExtractKeys<R extends RouteConfig> = R extends { children: ReadonlyArray<RouteConfig> }
? R['name'] | ExtractKeys<R['children'][number]>
: R['name'];
函数签名将是:
function getFlat<R extends RouteConfig>(routeConfig: readonly R[]):
Record<ExtractKeys<R>, RouteConfig> {
// Implementation doesn't matter.
return routeConfig as any;
}
const flat = getFlat([{
name: 'a',
path: 'a',
}, {
name: 'b',
path: 'b',
children: [{
name: 'c',
path: 'c',
}]
}] as const); // Record<"a" | "b" | "c", RouteConfig>
推荐阅读
- ios - 我的证书签名请求的公用名到底是什么
- matplotlib - Matplotlib 折线图动画
- c++ - Makefile,为什么每次都要重新编译?
- reactjs - 显示旧+新状态
- python - 根据 pandas 中的条件更改数据框的所有值
- javascript - 部分更改 Select (Ant Design) 中的文本颜色
- python-3.x - 如何自动回答python输入
- c# - Azure 应用服务 websocket 缓冲区缓冲区大小限制?
- angular - Angular 10 + Nativescript 多部分文件上传
- asp.net - 在 asp.net 应用程序中路由到 /login 和 /{PageName} 不起作用