mat*_*zav 8 recursion types typescript
TypeScript 允许您编写递归类型,但无法深入了解代码在较低级别(即深度)中如何变化。例如,下面的代码在所有级别上都具有相同类型的签名,并且我们必须在每个级别上手动检查是否存在属性sub。
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)
Run Code Online (Sandbox Code Playgroud)
我正在寻找的是一个类型签名,它可以为我们提供函数在特定深度返回的内容的具体证据。
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)
Run Code Online (Sandbox Code Playgroud)
这样,我们就不必在每个级别检查属性,sub因为类型签名已经包含该信息。
我有一种感觉,这可能可以通过条件类型来实现,但没有具体的证据。
你知道我怎样才能实现这一目标吗?
在 TS 允许对类型进行基本算术运算之前number,您可以使用递减计数器,就像用于Decr具有特定深度的所有递归类型一样:
type Decr = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] // add to a reasonable amount
type Recurse<N extends number> = N extends 0 ?
{ foo: string } :
{ foo: string; sub: Recurse<Decr[N]> }
function recurse<N extends number>(depth: N): Recurse<N> {
if (depth === 0) return { foo: 'hey' } as Recurse<N>
return {
foo: 'hey',
sub: recurse(depth - 1),
} as Recurse<N>
}
Run Code Online (Sandbox Code Playgroud)
type Decr9 = Decr[9] // 8
// compiles now
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)
Run Code Online (Sandbox Code Playgroud)
我认为您可能可以得到一些与递归条件类型一起使用的东西,但我建议不要使用这样的解决方案。毕竟,如果有人调用, 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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2848 次 |
| 最近记录: |