【发布时间】:2021-12-30 13:33:58
【问题描述】:
我有一个递归类型,它从嵌套对象中提取索引并将它们放入一个扁平的强类型元组中,如下所示:
type NestedRecord = Record<string, any>
type RecursiveGetIndex<
TRecord extends NestedRecord,
TPreviousIndices extends any[] = []
> = {
[K in keyof TRecord]: TRecord[K] extends NestedRecord
? RecursiveGetIndex<
TRecord[K],
AppendToTuple<TPreviousIndices,K>
>
: AppendToTuple<TPreviousIndices, K>
}[keyof TRecord]
type AppendToTuple<T extends any[], U> = [...T, U]
当使用嵌套对象类型的具体实例调用时,它可以正常工作,例如:
type AnIndex = RecursiveGetIndex<{ foo: { bar: { baz: number}}}>
换句话说,正如预期的那样,AnIndex 被键入为["foo", "bar", "baz"]
但是,当我尝试在函数中使用 Recursive 类型时,出现递归错误:
function doSomething<T extends NestedRecord>(arg:T){
type Nested = RecursiveGetIndex<T>
const doMore = (n: Nested) => {
console.log(n) //Type instantiation is excessively deep and possibly nested
}
}
哪一种对我来说有意义,因为 TS 并不知道T 的递归深度可能有多大。
正确吗?为什么 TS 不等到它看到 doSomething 被实例化后才担心递归?
而且,如果我事先知道传递给函数的arg 永远不会超过 TS 递归限制(我相信是 50),是否有某种方法可以避免该错误。即,我可以以某种方式告诉 typescript 吗?
我已经看到了基本上通过使用递减数组类型来限制递归的解决方案,例如this SO answer。这是我能做到的最好的吗?
更新
根据船长-yossarian 的建议,以下工作:
type RecursiveGetIndex<
TRecord extends NestedRecord,
TPreviousIndices extends any[] = [],
TDepth extends number = 5
> = 10 extends TPreviousIndices["length"] ? TPreviousIndices : {
[K in keyof TRecord]: TRecord[K] extends NestedRecord
? RecursiveGetIndex<
TRecord[K],
AppendToTuple<TPreviousIndices,K>
>
: AppendToTuple<TPreviousIndices, K>
}[keyof TRecord]
但是,如果此数字大于 10,则会再次出现错误。我原以为应该是 50。我的类型是否比我想象的更递归?
【问题讨论】:
-
这里catchts.com/recursive-ds你可以找到有限制的递归类型。至于第二个例子,TS 等不及你调用这个函数了,因为这是两个不同的阶段
-
blah,像这样的递归类型以一种奇怪/有趣的方式进行评估,我不知道有什么好的方法来处理这里的问题。反正我没发现什么好东西。
-
@captain-yossarian,这很聪明。在我的代码中使用它看起来像以
= 10 extends TPreviousIndices["length"] ? TPreviousIndices : //etc开头的类型有效,但如果我将其设为 11,则会出现错误。出于 TS 限制的目的,每个级别的递归都超过 1 是否有某种原因? -
@sam256 你能提供一个你如何称呼它的例子吗?
-
我将编辑我的问题,以便我可以放入操场链接
标签: typescript typescript-generics