嵌套类型的模板文字类型
Template literal type for a nested type
给定一个两层嵌套类型(层数不多也不少):
export type SomeNested = {
someProp: {
someChild: string
someOtherChild: string
}
someOtherProp: {
someMoreChildren: string
whatever: string
else: string
}
}
我想要以下联合类型:
"someProp.someChild" | "someProp.someOtherChild" | "someOtherProp.someMoreChildren" | "someOtherProp.whatever" | "someOtherProp.else"
.
我尝试了一些类似
的方法
type FirstLevel = keyof SomeNested
type SecondLevel = SomeNested[FirstLevel]
type Dot = `${FirstLevel}.${SecondLevel}`
但我可能遗漏了一些条件。
有人能给我指出正确的方向吗?
谢谢!
请注意,此题专门要求获取恰好包含两个级别的对象类型的虚线路径的并集。对于那些对任意深度对象的虚线路径并集感兴趣的人,您应该改为查看 。
通过 indexing into SomeNested
with the union of its known keys type FirstLevel = keyof SomeNested
,您得到了已知 属性 类型的联合:
type X = SomeNested[FirstLevel];
/* type X = {
someChild: string;
someOtherChild: string;
} | {
someMoreChildren: string;
whatever: string;
else: string;
} */
并且该联合的键将只是出现在该联合的所有成员中的键(对于您的示例,这根本不是什么):
type SecondLevel = keyof SomeNested[FirstLevel] // never
基本上,通过创建这些联合,您已经丢弃了有关 SomeNested
的特定键与其特定 属性 类型之间的对应关系的信息。要修复它,您基本上需要遍历 SomeNested
的键并分别查看每个键的子属性。
一种方法是使用 mapped type,它可以让您遍历键,然后为每个键创建一个 属性。例如:
type Mapped = { [K in keyof SomeNested]:
`${K}.${Extract<keyof SomeNested[K], string>}`
}
/* type Mapped = {
someProp: "someProp.someChild" | "someProp.someOtherChild";
someOtherProp: "someOtherProp.someMoreChildren" |
"someOtherProp.whatever" | "someOtherProp.else";
} */
Mapped
的每个 属性 都是一个 template literal type which starts with a particular key K
from keyof SomeNested
, followed by a dot, and then followed by the union of string keys from the corresponding property SomeNested[K]
. (Ideally you could just write ${keyof SomeNested[K]}
, but the compiler does not realize that these will definitely be strings for all possible K
, so we can use the Extract<T, U>
utility type 以说服编译器我们只查看 string
兼容键)。
当然你并不是真的想要 Mapped
,一个与 SomeNested
具有相同键的对象类型。但是您确实需要其 属性 类型的并集,因此 现在 您可以使用其键的并集对其进行索引:
type Dot = { [K in keyof SomeNested]:
`${K}.${Extract<keyof SomeNested[K], string>}`
}[keyof SomeNested]
/* type Dot = "someProp.someChild" | "someProp.someOtherChild" |
"someOtherProp.someMoreChildren" | "someOtherProp.whatever" | "someOtherProp.else" */
好了!
给定一个两层嵌套类型(层数不多也不少):
export type SomeNested = {
someProp: {
someChild: string
someOtherChild: string
}
someOtherProp: {
someMoreChildren: string
whatever: string
else: string
}
}
我想要以下联合类型:
"someProp.someChild" | "someProp.someOtherChild" | "someOtherProp.someMoreChildren" | "someOtherProp.whatever" | "someOtherProp.else"
.
我尝试了一些类似
的方法type FirstLevel = keyof SomeNested
type SecondLevel = SomeNested[FirstLevel]
type Dot = `${FirstLevel}.${SecondLevel}`
但我可能遗漏了一些条件。 有人能给我指出正确的方向吗?
谢谢!
请注意,此题专门要求获取恰好包含两个级别的对象类型的虚线路径的并集。对于那些对任意深度对象的虚线路径并集感兴趣的人,您应该改为查看
通过 indexing into SomeNested
with the union of its known keys type FirstLevel = keyof SomeNested
,您得到了已知 属性 类型的联合:
type X = SomeNested[FirstLevel];
/* type X = {
someChild: string;
someOtherChild: string;
} | {
someMoreChildren: string;
whatever: string;
else: string;
} */
并且该联合的键将只是出现在该联合的所有成员中的键(对于您的示例,这根本不是什么):
type SecondLevel = keyof SomeNested[FirstLevel] // never
基本上,通过创建这些联合,您已经丢弃了有关 SomeNested
的特定键与其特定 属性 类型之间的对应关系的信息。要修复它,您基本上需要遍历 SomeNested
的键并分别查看每个键的子属性。
一种方法是使用 mapped type,它可以让您遍历键,然后为每个键创建一个 属性。例如:
type Mapped = { [K in keyof SomeNested]:
`${K}.${Extract<keyof SomeNested[K], string>}`
}
/* type Mapped = {
someProp: "someProp.someChild" | "someProp.someOtherChild";
someOtherProp: "someOtherProp.someMoreChildren" |
"someOtherProp.whatever" | "someOtherProp.else";
} */
Mapped
的每个 属性 都是一个 template literal type which starts with a particular key K
from keyof SomeNested
, followed by a dot, and then followed by the union of string keys from the corresponding property SomeNested[K]
. (Ideally you could just write ${keyof SomeNested[K]}
, but the compiler does not realize that these will definitely be strings for all possible K
, so we can use the Extract<T, U>
utility type 以说服编译器我们只查看 string
兼容键)。
当然你并不是真的想要 Mapped
,一个与 SomeNested
具有相同键的对象类型。但是您确实需要其 属性 类型的并集,因此 现在 您可以使用其键的并集对其进行索引:
type Dot = { [K in keyof SomeNested]:
`${K}.${Extract<keyof SomeNested[K], string>}`
}[keyof SomeNested]
/* type Dot = "someProp.someChild" | "someProp.someOtherChild" |
"someOtherProp.someMoreChildren" | "someOtherProp.whatever" | "someOtherProp.else" */
好了!