【问题标题】:Nested object keys type to mapped union嵌套对象键类型到映射联合
【发布时间】:2021-12-11 02:42:08
【问题描述】:

我想创建一个类型 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```

【问题讨论】:

  • 请提供可重现的例子:NestedNav
  • 我认为它的外观并不重要。它可以只是一个对象。我认为您需要使用条件类型(扩展)来处理它,以使其他内容有所不同。
  • @captain-yossarian 更新了答案,也许现在对你来说更清楚了。

标签: typescript react-navigation union-types mapped-types nested-types


【解决方案1】:

这是可能的,但它需要对类型进行少量重构。 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>

Playground

键入Prefix 代表任何导航名称。

type Nav 表示有效的导航类型。

type GetNames 递归地遍历 nav 类型并将 tag 属性添加到 Cache(如果存在)。

【讨论】:

    猜你喜欢
    • 2022-01-03
    • 2021-12-11
    • 1970-01-01
    • 2023-01-13
    • 2020-09-27
    • 2013-08-01
    • 1970-01-01
    • 2017-05-27
    • 2018-03-20
    相关资源
    最近更新 更多