映射联合的嵌套对象键类型
Nested object keys type to mapped union
我想创建一个类型 NestedKeys
迭代给定的嵌套类型 RootNav
并收集值为 Nested<T>
的所有键并使其成为包含字符串的联合类型键,同时遵循嵌套结构(可能是递归的?)
type Nav = {
[key: string]: NestedNav<Nav> | object | undefined
}
type NestedNav<T extends Nav> = T
type RootNav = {
LoginNav: NestedNav<LoginNav>;
RegistrationNav: NestedNav<RegistrationNav>;
AppNav: NestedNav<AppNav>
}
type AppNav = {
MainNav: NestedNav<MainNav>;
FooScreen: undefined
BarScreen: {id: string}
};
type LoginNav = {
LoginScreen: undefined
}
type RegistrationNav = {
RegistrationScreen: undefined
}
type MainNav = {
HomeScreen: undefined
ProfileScreen: undefined
}
最终结果应该是
type NestedKeys<RootNav>
// → "RootNav" | "LoginNav" | "RegistrationNav" | "AppNav" | "MainNav"
我有这样的想法,但不知道如何正确地做到这一点。这不起作用:
type NestedKeys<T extends Nav> = T[keyof T] extends NestedNav<any> ? NestedKeys<T[keyof T]> : T```
可以做到,但需要对类型进行少量重构。
TypeScript 不支持 macros
。没有像javascript那样的value.toString
的概念。这意味着您无法获得某种类型名称的字符串表示形式。
这就是我添加 tag
属性:
的原因
type Prefix = `${string}Nav`
type Nav =
& Record<'tag', Prefix>
& {
[key: Prefix]: undefined | Nav
}
type NestedNav<T extends Nav> = T
type RootNav = {
tag: 'RootNav'
LoginNav: NestedNav<LoginNav>;
RegistrationNav: NestedNav<RegistrationNav>;
AppNav: NestedNav<AppNav>
}
type AppNav = {
tag: 'AppNav'
MainNav: NestedNav<MainNav>;
FooScreen: undefined
BarScreen: { id: string }
};
type LoginNav = {
tag: 'LoginNav';
LoginScreen: undefined
}
type RegistrationNav = {
tag: 'RegistrationNav';
RegistrationScreen: undefined
}
type MainNav = {
tag: 'MainNav';
HomeScreen: undefined
ProfileScreen: undefined
}
type DefaultTag<T> = T extends { tag: infer Tag } ? Tag : never
type GetNames<T, Cache extends any[] = [DefaultTag<T>]> =
(T extends string
? Cache[number]
: {
[Prop in keyof T]:
(T[Prop] extends { tag: infer Tag }
? GetNames<T[Prop], [...Cache, Tag]>
: GetNames<T[Prop], Cache>)
}[keyof T]
)
type Result = GetNames<RootNav>
type Prefix
表示任何导航名称。
type Nav
表示有效的导航类型。
type GetNames
递归遍历 nav
type 并添加 tag
属性 到 Cache
如果存在
我想创建一个类型 NestedKeys
迭代给定的嵌套类型 RootNav
并收集值为 Nested<T>
的所有键并使其成为包含字符串的联合类型键,同时遵循嵌套结构(可能是递归的?)
type Nav = {
[key: string]: NestedNav<Nav> | object | undefined
}
type NestedNav<T extends Nav> = T
type RootNav = {
LoginNav: NestedNav<LoginNav>;
RegistrationNav: NestedNav<RegistrationNav>;
AppNav: NestedNav<AppNav>
}
type AppNav = {
MainNav: NestedNav<MainNav>;
FooScreen: undefined
BarScreen: {id: string}
};
type LoginNav = {
LoginScreen: undefined
}
type RegistrationNav = {
RegistrationScreen: undefined
}
type MainNav = {
HomeScreen: undefined
ProfileScreen: undefined
}
最终结果应该是
type NestedKeys<RootNav>
// → "RootNav" | "LoginNav" | "RegistrationNav" | "AppNav" | "MainNav"
我有这样的想法,但不知道如何正确地做到这一点。这不起作用:
type NestedKeys<T extends Nav> = T[keyof T] extends NestedNav<any> ? NestedKeys<T[keyof T]> : T```
可以做到,但需要对类型进行少量重构。
TypeScript 不支持 macros
。没有像javascript那样的value.toString
的概念。这意味着您无法获得某种类型名称的字符串表示形式。
这就是我添加 tag
属性:
type Prefix = `${string}Nav`
type Nav =
& Record<'tag', Prefix>
& {
[key: Prefix]: undefined | Nav
}
type NestedNav<T extends Nav> = T
type RootNav = {
tag: 'RootNav'
LoginNav: NestedNav<LoginNav>;
RegistrationNav: NestedNav<RegistrationNav>;
AppNav: NestedNav<AppNav>
}
type AppNav = {
tag: 'AppNav'
MainNav: NestedNav<MainNav>;
FooScreen: undefined
BarScreen: { id: string }
};
type LoginNav = {
tag: 'LoginNav';
LoginScreen: undefined
}
type RegistrationNav = {
tag: 'RegistrationNav';
RegistrationScreen: undefined
}
type MainNav = {
tag: 'MainNav';
HomeScreen: undefined
ProfileScreen: undefined
}
type DefaultTag<T> = T extends { tag: infer Tag } ? Tag : never
type GetNames<T, Cache extends any[] = [DefaultTag<T>]> =
(T extends string
? Cache[number]
: {
[Prop in keyof T]:
(T[Prop] extends { tag: infer Tag }
? GetNames<T[Prop], [...Cache, Tag]>
: GetNames<T[Prop], Cache>)
}[keyof T]
)
type Result = GetNames<RootNav>
type Prefix
表示任何导航名称。
type Nav
表示有效的导航类型。
type GetNames
递归遍历 nav
type 并添加 tag
属性 到 Cache
如果存在