-
Notifications
You must be signed in to change notification settings - Fork 0
/
traversable.ts
124 lines (114 loc) · 3.83 KB
/
traversable.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/**
* ////////////////////////////////////////////
* // 💀 THIS MODULE HAS BEEN DEPRECATED 💀
* //
* // Use {@link Tree `Tree`} instead
* ////////////////////////////////////////////
*/
export {
/** @deprecated use {@link Tree `Tree`} instead */
traversable,
/** @deprecated use {@link Tree `Tree`} instead */
traversal,
}
import type { any } from "../any/exports.js"
import type { nonempty } from "../nonempty/nonempty.js"
import type { empty } from "../empty/empty.js"
import type { Tree } from "../tree/exports.js"
import type { never } from "../never/exports.js"
///////////////////////
/// 💀 DEPRECATED 💀
declare namespace impl {
/** @deprecated use {@link Tree.unfold `Tree.unfold`} instead */
type unfold<path extends any.path, leaf = unknown>
= path extends empty.array ? leaf
: path extends nonempty.pathLeft<infer init, infer last>
? unfold<init, any.named<[𝐥𝐚𝐛𝐞𝐥: last, 𝐯𝐚𝐥𝐮𝐞: leaf]>>
: never
;
}
///////////////////////
/// 💀 DEPRECATED 💀
/** @deprecated use {@link Tree.unfold `Tree.unfold`} instead */
type unfold<leaf, path extends any.path> = impl.unfold<path, leaf>
///////////////////////
/// 💀 DEPRECATED 💀
/**
* {@link by `traversable.by`} is a type-constructor that takes a path describing a tree and,
* via induction, constructs the tree it describes.
*
* See also: {@link of `traversable.of`}
*
* When used as an invariant, this constructor is a particularly good example of the
* {@link https://en.wikipedia.org/wiki/Curry%E2%80%93Howard_correspondence _natural correspondence_}
* between computation and propositional logic.
*
* By this interpretation, a program that builds the data structure that a path called `p` describes
* is the proof that such a data structure can be built -- this process is sometimes called "proof
* by construction".
*
* What does that look like in practice though?
*
* @example
* import type { any } from "any-ts"
*
* declare function hasPath<const path extends any.path>
* (...path: path): <const tree>(tree: tree) => tree is tree & traversable.by<path>
*
* // if "there exists" a path `abc.def.ghi` in the input object,
* // let the output object's type reflect that information
* const hasAbcDefGhi = hasPath("abc", "def", "ghi")
*
* declare const blob: { xyz: "1223" }
*
* if (hasAbcDefGhi(blob)) {
* blob
* } // ^? const blob: { xyz: "1223" } & { abc: { def: { ghi: unknown } } }
*/
///////////////////////
/// 💀 DEPRECATED 💀
/** @deprecated use {@link Tree.traversableBy `Tree.traversableBy`} instead */
type by<
invariant extends any.path,
type extends
| impl.unfold<invariant>
= impl.unfold<invariant>
> = type
///////////////////////
/// 💀 DEPRECATED 💀
/** @deprecated use {@link Tree `Tree`} instead */
declare namespace traversable {
export {
///////////////////////
/// 💀 DEPRECATED 💀
by,
///////////////////////
/// 💀 DEPRECATED 💀
unfold,
}
///////////////////////
/// 💀 DEPRECATED 💀
/** @deprecated use {@link Tree.unfold `Tree.unfold`} instead */
type unfold<path extends any.path, leaf = unknown>
= path extends empty.array ? leaf
: path extends nonempty.pathLeft<infer init, infer last>
? unfold<init, any.named<[last: last, leaf: leaf]>>
: never
;
}
///////////////////////
/// 💀 DEPRECATED 💀
/** @deprecated use {@link Tree.traversal `Tree.traversal`} instead */
declare namespace traversal {
///////////////////////
/// 💀 DEPRECATED 💀
/** @deprecated use {@link Tree.traversal `Tree.traversal`} instead */
type of<
tree,
path extends any.array<any.index>,
> = path extends empty.path ? tree
: path extends nonempty.path<any.keyof<tree, infer head>, infer tail>
? traversal.of<tree[head], tail>
: never.close.unmatched_expr
;
}