将递归数组/对象作为 TypeScript 中的扁平对象类型返回 [英] Return recursive array/object as flattened object type in TypeScript
问题描述
我正在尝试编写一个函数,该函数采用递归对象/数组,其中每个节点都有一个名称",并且可以选择子节点".然后我想要一个函数,它采用这种递归结构并返回一个类型安全的对象,其中递归出现的名称"是键,节点是值;因此,如果您尝试访问不存在的密钥,它会在编译期间为您出错.
I'm trying to write a function that takes a recursive object/array where each node has a "name", and optionally, "children". I would like to then have a function which takes this recursive structure and return a type-safe object where the recursively occurring "name"s are the keys, and the node is the values; so it would error out for you during compile time if you tried to access a key that didn't exist.
到目前为止,我能够以这种方式识别顶级名称(名称a"和b"),因此 flat
将被识别为 Record<";一个"|b",RouteConfigItem.
So far I was able to get the top-level names recognized this way (names "a" and "b") so that flat
would be recognized as 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
被识别为 记录a"|b"|c",RouteConfigItem.
But how could I make it also see the non-top-level names as well? Only caring about the types, not the implementation in the body of getFlat()
, I would like for flat
to be recognized as Record<"a" | "b" | "c", RouteConfigItem<"a" | "b" | "c">>
.
顺便说一下,代码示例在我的 WebStorm 中似乎对我有用,但在 typescriptlang.org/play 中似乎不起作用,所以我没有包含这样的链接.
By the way, the code example seemed to work for me in my WebStorm, but does not seem to work in typescriptlang.org/play, so I didn't include such a link.
推荐答案
我稍微简化了 RouteConfig
定义:
I've simplified a bit the RouteConfig
definition:
type RouteConfig = {
name: string,
path: string,
children?: ReadonlyArray<RouteConfig>
};
现在要提取密钥,您可以:
Now to extract keys you can:
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>
这篇关于将递归数组/对象作为 TypeScript 中的扁平对象类型返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!