我需要在一个对象内部使用所有的基本类型(加上null)。
到目前为止,我发现的所有答案都只适用于简单的对象。但是我的那些是深度嵌套的,并且有包含对象的数组。
例如,对于这个对象:
const Data = {
a: {
x: "foo",
},
b: {
x: [123, 45],
y: [
{
x: null,
},
{ x: Symbol(666) },
],
},
};
我尝试派生类型(字符串|号码|零|符号)
type foo = DERIVE<typeof Data> // foo = string | number | null | symbol
到目前为止,我在SO上找到的东西让我走了这么远(这完全是一团糟,对不起):
type RecursiveValues<T> = {
[Prop in keyof T]:
(T[Prop] extends Array<any> ? RecursiveValues<T[Prop][number]> : T[Prop] extends object
? RecursiveValues<T[Prop]>
: T[Prop])
}[keyof T]
type TestValues = RecursiveValues<typeof Data>
2条答案
按热度按时间pn9klfpd1#
这件事有两个难点。
1.该类型需要递归才能钻取到所有叶子
1.数组需要特殊处理,因为
keyof unknown[]
将包含数组所具有的方法。你想要这样的东西:
这里
Primitive
类型的存在是为了知道何时停止钻取。如果遇到这些类型,则递归停止。您将需要使用希望以其结束的值来自定义此列表。现在我们可以转到
DERIVE
类型本身。让我们一行一行地走:T extends Primitive ? T
如果类型是基元,则返回它。否则继续。: T extends readonly unknown[] ? DERIVE<T[number]>
如果类型是数组,则派生其成员的类型。否则继续。: DERIVE<T[keyof T]>
其他检查失败,因此我们假设这是一个对象类型,并派生T
的每个属性类型。现在,这将按照您的预期工作:
见操场
lf5gs5x22#
请注意,如果希望值为文字,则可能需要定义对象
as const