TypeScript 允许您组合递归类型,但无法深入了解代码在较低级别(即深度)中的变化情况。例如,下面的代码在所有级别都具有相同类型的签名,我们必须在每个级别手动检查是否存在 sub
属性(property)。
type Recurse = { foo: string; sub?: Recurse }
function recurse(depth: number): Recurse {
if (depth === 0) return { foo: 'hey' }
return {
foo: 'hey',
sub: recurse(depth - 1),
}
}
const qux = recurse(5)
我正在寻找的是一个类型签名,它可以为我们提供函数在特定深度返回什么的具体证据。
const qux0: { foo: string } = recurse(0)
const qux1: { foo: string, sub: { foo: string } } = recurse(1)
const qux2: { foo: string, sub: { foo: string, sub: { foo: string }} } = recurse(2)
这样,我们就不必在每个级别检查
sub
属性,因为类型签名已经打包了该信息。我有一种感觉,这可能可以通过条件类型实现,但没有具体证据。
你知道我怎么能做到这一点吗?
最佳答案
我认为您可能可以使用递归条件类型获得一些东西,但我建议不要使用这样的解决方案。毕竟,如果有人要调用 recurse(5000)
返回类型会很大。
您可以轻松构建基于映射类型的解决方案,您可以在其中添加最多特定深度的子项类型:
type Recurse<T extends number = number> = {
foo: string;
sub: RecurseChildren extends Record<T, infer C> ? C : Recurse
}
interface RecurseChildren {
0: undefined;
1: Recurse<0>
2: Recurse<1>
3: Recurse<2>
4: Recurse<3>
5: Recurse<4>
6: Recurse<5>
7: Recurse<6>
8: Recurse<7>
9: Recurse<8>
10: Recurse<9>
}
function recurse<T extends number>(depth: T): Recurse<T> {
if (depth === 0) return { foo: 'hey', sub: undefined as any }
return {
foo: 'hey',
sub: recurse(depth - 1) as any,
}
}
const qux = recurse(5)
qux.sub.sub.sub.sub.sub.sub // last one is undefined
Playground Link
关于具有特定深度的 TypeScript 递归类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60168740/