tuplerone 4.0.0-next.4 → 4.0.0-next.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -246
- package/dist/tuplerone.d.mts +83 -0
- package/dist/tuplerone.mjs +301 -0
- package/dist/tuplerone.mjs.map +1 -0
- package/package.json +44 -83
- package/dist/Node.d.ts +0 -13
- package/dist/Tuple.d.ts +0 -10
- package/dist/deep.d.ts +0 -6
- package/dist/graph.cjs +0 -87
- package/dist/graph.cjs.map +0 -7
- package/dist/graph.d.ts +0 -6
- package/dist/graph.js +0 -66
- package/dist/graph.js.map +0 -7
- package/dist/memoize.d.ts +0 -6
- package/dist/shallow.d.ts +0 -23
- package/dist/tuplerone.cjs +0 -164
- package/dist/tuplerone.cjs.map +0 -7
- package/dist/tuplerone.d.ts +0 -4
- package/dist/tuplerone.js +0 -143
- package/dist/tuplerone.js.map +0 -7
package/README.md
CHANGED
|
@@ -1,279 +1,72 @@
|
|
|
1
1
|
<h1 align="center"><a href="https://github.com/slikts/tuplerone"><img width="550" src="https://raw.githubusercontent.com/slikts/tuplerone/master/logo.svg?sanitize=true" alt="tuplerone"></a></h1>
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
|
-
<a href="https://
|
|
5
|
-
<a href="https://coveralls.io/github/slikts/tuplerone"><img src="https://img.shields.io/coveralls/slikts/tuplerone.svg" alt="Coveralls"></a>
|
|
6
|
-
<a href="https://github.com/semantic-release/semantic-release"><img src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg" alt="semantic-release"></a>
|
|
7
|
-
<a href="https://github.com/slikts/tuplerone"><img src="https://img.shields.io/github/license/slikts/tuplerone.svg" alt="License"></a>
|
|
4
|
+
<a href="https://img.shields.io/npm/v/tuplerone.svg?style=flat"><img src="https://img.shields.io/npm/v/tuplerone.svg?style=flat" alt="View this project on npm"></a>
|
|
8
5
|
</p>
|
|
9
6
|
|
|
10
7
|
<p align="center">A lightweight, efficient tuple and value object implementation for JavaScript and TypeScript.</p>
|
|
11
8
|
|
|
12
9
|
---
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
In JavaScript, objects with the same contents aren't equal:
|
|
15
12
|
|
|
16
|
-
```
|
|
17
|
-
(1, 2, 3) == (1, 2, 3) # → True
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
A JavaScript version of something similar looks like this:
|
|
21
|
-
|
|
22
|
-
```js
|
|
23
|
-
'[1,2,3]' === '[1,2,3]'; // → true
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
Except it's using a string and would need to be unserialized with `JSON.parse()` to allow accessing the separate members. Moreover, JSON is limited in what values can be serialized.
|
|
27
|
-
|
|
28
|
-
You could alternatively use `"1,2,3"` and `String.split(",")`, but it's also not very convenient. Just using an array doesn't work:
|
|
29
|
-
|
|
30
|
-
```js
|
|
13
|
+
```ts
|
|
31
14
|
[1, 2, 3] === [1, 2, 3]; // → false
|
|
32
15
|
```
|
|
33
16
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
```js
|
|
37
|
-
Tuple(1, 2, 3) === Tuple(1, 2, 3);
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Example use case for tuples is dealing with memoization like React's [`memo()`][memo] or `PureComponent`, since you can pass lists as props to components without forcing re-renders or manually caching the list. It's also useful for using multiple values as keys with `Map()`. In general, it's just a nice thing to have in your toolbox.
|
|
41
|
-
|
|
42
|
-
**[Try Tuplerone in a sandbox][sandbox]**
|
|
17
|
+
Tuplerone fixes this. The same arguments always produce the same object reference, so `===` just works:
|
|
43
18
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
This library is:
|
|
47
|
-
|
|
48
|
-
- _tiny_ (bundle size is [under one kilobyte][tiny] compressed), with no dependencies
|
|
49
|
-
- _well-typed_ using TypeScript (but can still be used from JavaScript, of course)
|
|
50
|
-
- _well-tested_ with full coverage
|
|
51
|
-
- _efficient_ using an ES2015 [`WeakMap`][weakmap]-based directed acyclic graph for lookups
|
|
52
|
-
|
|
53
|
-
The `Tuple` objects are:
|
|
54
|
-
|
|
55
|
-
- _immutable_ – properties cannot be added, removed or changed, and it's enforced with [`Object.freeze()`][frozen]
|
|
56
|
-
- [array-like] – tuple members can be accessed by indexing, and there's a `length` property, but no `Array` prototype methods
|
|
57
|
-
- [iterable] – tuple members can be iterated over, for example, using [`for-of`][for-of] loops or spread syntax
|
|
58
|
-
|
|
59
|
-
There exists a [stage-1 proposal][proposal] for adding a tuple type to JavaScript and a [different stage-1 proposal][composite] for adding a more limited value-semantic type.
|
|
60
|
-
|
|
61
|
-
## Theory
|
|
62
|
-
|
|
63
|
-
[Tuples] are **finite ordered sequences of values** that serve two main purposes in programming languages:
|
|
64
|
-
|
|
65
|
-
- grouping together heterogenous (mixed) data types within a static type system (this doesn't apply to a dynamically typed language like JavaScript)
|
|
66
|
-
- simplifying value-semantic comparisons of lists, which is what this library is mainly about
|
|
67
|
-
|
|
68
|
-
### Value semantics
|
|
69
|
-
|
|
70
|
-
A simple way to explain value semantics is to look at the difference between primitive values (like numbers and strings) and object values in JavaScript. Primitives are value-semantic by default,
|
|
71
|
-
meaning that the default comparison methods (`==`, `===` and `Object.is()`) compare primitive values by their contents, so, for example, any string is equal to any other string created with the same contents:
|
|
72
|
-
|
|
73
|
-
```js
|
|
74
|
-
'abc' === 'abc'; // → true, because both string literals create a value with the same contents
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
The contents of primitive values are also immutable (can't change at runtime), so the results of comparing primitive value equality can't be invalidated by the contents of the values changing.
|
|
78
|
-
|
|
79
|
-
Meanwhile, each object value (instance) in JavaScript has a unique identity, so each instance is only equal to itself and not any other instances:
|
|
80
|
-
|
|
81
|
-
```js
|
|
82
|
-
[1, 2, 3] === [1, 2, 3]; // → false, because both array literals create separate array instances
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
Objects by default can't be thought of as their contents since the contents can change, and this is called reference semantics, since objects essentially represent a place in memory. The downside is that it makes reasoning about a program harder, since the programmer has to consider potential changes.
|
|
86
|
-
|
|
87
|
-
A more direct practical consequence of reference semantics is that comparing instances requires _deep comparisons_, such as [`_.isEqual()`][isequal] in lodash or serializing the object values to JSON:
|
|
88
|
-
|
|
89
|
-
```js
|
|
90
|
-
let a = [1, 2, 3];
|
|
91
|
-
let b = [1, 2, 3];
|
|
92
|
-
let result = JSON.stringify(a) === JSON.stringify(b); // → true, because it's a deep comparison
|
|
93
|
-
a.push(4); // a and b contents are now different, so the cached comparison result is invalid
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
Deep comparison results can't be reliably cached since the compared instances can change, and it's also less efficient than just being able to use `===` directly. An another thing that's not possible with reference semantics is combining different values to use as a composite key (such as with `Map` or `WeakMap`).
|
|
97
|
-
|
|
98
|
-
### Directed acyclic graphs
|
|
99
|
-
|
|
100
|
-
Directed acyclic graphs (DAGs) are a data structure that allows efficiently mapping a sequence of values to a unique object containing them, which is how this library is implemented. Specifically, it uses a `WeakMap` object (optionally a `Map` as well if mapping primitives) for each node, and the nodes are re-used for overlapping paths in the graph. Map access has constant time complexity, so the number of tuples created doesn't slow down access speed. Using `WeakMap` ensures that if the values used to create the tuple are dereferenced, the tuple object gets garbage collected.
|
|
101
|
-
|
|
102
|
-
## Installation
|
|
103
|
-
|
|
104
|
-
```sh
|
|
105
|
-
npm install tuplerone
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
```sh
|
|
109
|
-
yarn add tuplerone
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
```js
|
|
113
|
-
import { Tuple } from 'https://cdn.skypack.dev/tuplerone';
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
```html
|
|
117
|
-
<script src="https://unpkg.com/tuplerone/dist/tuplerone.umd.js"></script>
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## Usage
|
|
121
|
-
|
|
122
|
-
### `Tuple(…values)`
|
|
123
|
-
|
|
124
|
-
```js
|
|
19
|
+
```ts twoslash
|
|
125
20
|
import { Tuple } from 'tuplerone';
|
|
126
21
|
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
const b = Object('b');
|
|
130
|
-
const c = Object('c');
|
|
22
|
+
const a = { id: 1 };
|
|
23
|
+
const b = { id: 2 };
|
|
131
24
|
|
|
132
|
-
|
|
133
|
-
Tuple(a, b, c) === Tuple(a, b, c); // → true
|
|
134
|
-
Tuple(a, b) === Tuple(b, a); // → false
|
|
25
|
+
Tuple(a, b) === Tuple(a, b); // → true
|
|
135
26
|
|
|
136
|
-
//
|
|
27
|
+
// Use as composite Map key
|
|
137
28
|
const map = new Map();
|
|
138
|
-
map.set(Tuple(a, b),
|
|
139
|
-
|
|
140
|
-
// Nesting tuples
|
|
141
|
-
Tuple(a, Tuple(b, c)) === Tuple(a, Tuple(b, c)); // → true
|
|
142
|
-
|
|
143
|
-
// Using primitive values
|
|
144
|
-
Tuple(1, 'a', a); // → Tuple(3) [1, "a", Object("a")]
|
|
145
|
-
|
|
146
|
-
// Indexing
|
|
147
|
-
Tuple(a, b)[1]; // → Object("b")
|
|
148
|
-
|
|
149
|
-
// Checking arity
|
|
150
|
-
Tuple(a, b).length; // → 2
|
|
151
|
-
|
|
152
|
-
// Failing to mutate
|
|
153
|
-
Tuple(a, b)[0] = c; // throws an error
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
The tuple function caches or memoizes its arguments to produce the same tuple object for the same arguments.
|
|
157
|
-
|
|
158
|
-
### Types
|
|
159
|
-
|
|
160
|
-
The library is well-typed using TypeScript:
|
|
161
|
-
|
|
162
|
-
```ts
|
|
163
|
-
import { Tuple, Tuple0, Tuple1, Tuple2 } from 'tuplerone';
|
|
164
|
-
|
|
165
|
-
// Dummy object for use as key
|
|
166
|
-
const o = {};
|
|
167
|
-
|
|
168
|
-
const tuple0: Tuple0 = Tuple(); // 0-tuple
|
|
169
|
-
const tuple1: Tuple1<typeof o> = Tuple(o); // 1-tuple
|
|
170
|
-
const tuple2: Tuple2<typeof o, number> = Tuple(o, 1); // 2-tuple
|
|
171
|
-
|
|
172
|
-
Tuple(o) === Tuple(o, 1); // TS compile error due to different arities
|
|
173
|
-
|
|
174
|
-
// Spreading a TypeScript tuple:
|
|
175
|
-
Tuple(...([1, 2, 3] as const)); // → Tuple3<1, 2, 3>
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
In editors like VS Code, the type information is also available when the library is consumed as JavaScript.
|
|
179
|
-
|
|
180
|
-
### `CompositeSymbol(…values)`
|
|
181
|
-
|
|
182
|
-
It's possible to avoid creating an `Array`-like tuple for cases where iterating the tuple members isn't needed (for example, just to use it as a key):
|
|
183
|
-
|
|
184
|
-
```js
|
|
185
|
-
import { CompositeSymbol } from 'tuplerone';
|
|
186
|
-
|
|
187
|
-
typeof CompositeSymbol(1, 2, {}) === 'symbol'; // → true
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
A symbol is more space efficient than a tuple and can be used as a key for plain objects.
|
|
191
|
-
|
|
192
|
-
### `ValueObject(object)`
|
|
193
|
-
|
|
194
|
-
Tuplerone also includes a simple [value object] implementation:
|
|
195
|
-
|
|
196
|
-
```js
|
|
197
|
-
import { ValueObject } from 'tuplerone';
|
|
198
|
-
|
|
199
|
-
ValueObject({ a: 1, { b: { c: 2 } }}) === ValueObject({ a: 1, { b: { c: 2 } }}); // → true
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
Note that the passed objects are frozen with [`Object.freeze()`][frozen].
|
|
203
|
-
|
|
204
|
-
## Caveats
|
|
205
|
-
|
|
206
|
-
Since this is a userspace implementation, there are a number of limitations.
|
|
207
|
-
|
|
208
|
-
### At least one member must be an object to avoid memory leaks
|
|
209
|
-
|
|
210
|
-
Due to `WeakMap` being limited to using objects as keys, there must be at least one member of a tuple with the object type, or the tuples would leak memory. Trying to create tuples with only primitive members will throw an error.
|
|
211
|
-
|
|
212
|
-
```ts
|
|
213
|
-
Tuple(1, 2); // throws TypeError
|
|
214
|
-
Tuple(1, 2, {}); // works
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
`WeakMap` is an ES2015 feature which is difficult to polyfill (the [polyfills][polyfill] don't support frozen objects), but this applies less to environments like node or browser extensions.
|
|
218
|
-
|
|
219
|
-
#### `UnsafeTuple`
|
|
220
|
-
|
|
221
|
-
There is an `UnsafeTuple` type for advanced use cases where the values not being garbage-collectable is acceptable, so it doesn't require having an object member:
|
|
222
|
-
|
|
223
|
-
```js
|
|
224
|
-
import { UnsafeTuple as Tuple } from 'tuplerone';
|
|
225
|
-
|
|
226
|
-
Tuple(1, 2, 3) === Tuple(1, 2, 3); // → true
|
|
29
|
+
map.set(Tuple(a, b), 'pair');
|
|
30
|
+
map.get(Tuple(a, b)); // → 'pair'
|
|
227
31
|
```
|
|
228
32
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
tuplerone tuples are not supported by the relation comparison operators like `<`, whereas in a language like Python the following (comparing tuples by arity) would evaluate to true: `(1,) < (1, 2)`.
|
|
232
|
-
|
|
233
|
-
### `Array`-like but there's no `Array` prototypes methods
|
|
33
|
+
Useful for memoization (e.g. React's [`memo()`][memo]), composite `Map` keys, and anywhere you need structural equality without deep comparison.
|
|
234
34
|
|
|
235
|
-
|
|
35
|
+
## Features
|
|
236
36
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
The advantage of subclassing `Array` is ergonomic console representation (it's represented as an array would be), which is based on `Array.isArray()` and so requires subclassing `Array`.
|
|
37
|
+
- **Tiny**—[under 1KB][bundlephobia] compressed, zero dependencies
|
|
38
|
+
- **Well-typed**—full TypeScript support (works from JavaScript too)
|
|
39
|
+
- **Well-tested**—full test coverage
|
|
40
|
+
- **Efficient**—[`WeakMap`][weakmap]-based directed acyclic graph for lookups
|
|
41
|
+
- **Immutable**—tuples are frozen with [`Object.freeze()`][frozen]
|
|
42
|
+
- **Iterable**—supports [`for-of`][for-of], spread, and destructuring
|
|
244
43
|
|
|
245
|
-
|
|
44
|
+
## Documentation
|
|
246
45
|
|
|
247
|
-
|
|
46
|
+
**[Read the full documentation][docs]**
|
|
248
47
|
|
|
249
|
-
|
|
48
|
+
- [Getting Started][docs]
|
|
49
|
+
- [Tuple][docs-tuple]
|
|
50
|
+
- [CompositeSymbol][docs-composite-symbol]
|
|
51
|
+
- [ValueObject][docs-value-object]
|
|
52
|
+
- [Theory & Internals][docs-theory]
|
|
53
|
+
- [Caveats][docs-caveats]
|
|
250
54
|
|
|
251
|
-
|
|
252
|
-
(`Symbol`, `Boolean`, `String`, `Number`) that also don't require `new` and also are value-semantic. This means that `instanceof` doesn't work the same as for other objects, but can still be used like so:
|
|
55
|
+
## Related
|
|
253
56
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
```
|
|
57
|
+
- [TC39 Record & Tuple proposal][proposal]
|
|
58
|
+
- [TC39 Composite Keys proposal][composite]
|
|
257
59
|
|
|
60
|
+
[memo]: https://react.dev/reference/react/memo
|
|
258
61
|
[weakmap]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
|
|
259
|
-
[map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
|
|
260
|
-
[tuples]: https://en.wiktionary.org/wiki/tuple
|
|
261
|
-
[isequal]: https://lodash.com/docs/4.17.10#isEqual
|
|
262
62
|
[frozen]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
|
|
263
|
-
[composite]: https://github.com/bmeck/proposal-richer-keys/tree/master/compositeKey
|
|
264
|
-
[iterable]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol
|
|
265
|
-
[tuple]: https://en.wiktionary.org/wiki/tuple
|
|
266
|
-
[array-like]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections#Working_with_array-like_objects
|
|
267
63
|
[for-of]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of
|
|
268
|
-
[
|
|
269
|
-
[polyfill]: https://github.com/medikoo/es6-weak-map#readme
|
|
270
|
-
[value semantics]: https://en.wikipedia.org/wiki/Value_semantics
|
|
271
|
-
[value types]: https://en.wikipedia.org/wiki/Value_type_and_reference_type
|
|
272
|
-
[isequal]: https://lodash.com/docs/#isEqual
|
|
64
|
+
[bundlephobia]: https://bundlephobia.com/result?p=tuplerone
|
|
273
65
|
[proposal]: https://github.com/tc39/proposal-record-tuple
|
|
274
|
-
[
|
|
275
|
-
[
|
|
276
|
-
[
|
|
277
|
-
[
|
|
278
|
-
[
|
|
279
|
-
[
|
|
66
|
+
[composite]: https://github.com/bmeck/proposal-richer-keys/tree/master/compositeKey
|
|
67
|
+
[docs]: https://slikts.github.io/tuplerone/
|
|
68
|
+
[docs-tuple]: https://slikts.github.io/tuplerone/docs/usage/tuple
|
|
69
|
+
[docs-composite-symbol]: https://slikts.github.io/tuplerone/docs/usage/composite-symbol
|
|
70
|
+
[docs-value-object]: https://slikts.github.io/tuplerone/docs/usage/value-object
|
|
71
|
+
[docs-theory]: https://slikts.github.io/tuplerone/docs/theory
|
|
72
|
+
[docs-caveats]: https://slikts.github.io/tuplerone/docs/caveats
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
type TupleN<T extends readonly unknown[]> = Tuple<T[number]> & Readonly<T>;
|
|
3
|
+
interface Tuple0 extends Tuple<never> {
|
|
4
|
+
readonly length: 0;
|
|
5
|
+
}
|
|
6
|
+
/** Singleton */
|
|
7
|
+
type Tuple1<A> = TupleN<[A]>;
|
|
8
|
+
/** Pair */
|
|
9
|
+
type Tuple2<A, B> = TupleN<[A, B]>;
|
|
10
|
+
/** Triple */
|
|
11
|
+
type Tuple3<A, B, C> = TupleN<[A, B, C]>;
|
|
12
|
+
/** Quadruple */
|
|
13
|
+
type Tuple4<A, B, C, D> = TupleN<[A, B, C, D]>;
|
|
14
|
+
/** Quintuple */
|
|
15
|
+
type Tuple5<A, B, C, D, E> = TupleN<[A, B, C, D, E]>;
|
|
16
|
+
/** Sextuple */
|
|
17
|
+
type Tuple6<A, B, C, D, E, F> = TupleN<[A, B, C, D, E, F]>;
|
|
18
|
+
/** Septuple */
|
|
19
|
+
type Tuple7<A, B, C, D, E, F, G> = TupleN<[A, B, C, D, E, F, G]>;
|
|
20
|
+
/** Octuple */
|
|
21
|
+
type Tuple8<A, B, C, D, E, F, G, H> = TupleN<[A, B, C, D, E, F, G, H]>;
|
|
22
|
+
type CompositeSymbol<T extends readonly unknown[]> = {
|
|
23
|
+
t: T;
|
|
24
|
+
} & symbol;
|
|
25
|
+
declare const CompositeSymbol0: CompositeSymbol<readonly []>;
|
|
26
|
+
type CompositeSymbol1<A> = CompositeSymbol<[A]>;
|
|
27
|
+
type CompositeSymbol2<A, B> = CompositeSymbol<[A, B]>;
|
|
28
|
+
type CompositeSymbol3<A, B, C> = CompositeSymbol<[A, B, C]>;
|
|
29
|
+
type CompositeSymbol4<A, B, C, D> = CompositeSymbol<[A, B, C, D]>;
|
|
30
|
+
type CompositeSymbol5<A, B, C, D, E> = CompositeSymbol<[A, B, C, D, E]>;
|
|
31
|
+
type CompositeSymbol6<A, B, C, D, E, F> = CompositeSymbol<[A, B, C, D, E, F]>;
|
|
32
|
+
type CompositeSymbol7<A, B, C, D, E, F, G> = CompositeSymbol<[A, B, C, D, E, F, G]>;
|
|
33
|
+
type CompositeSymbol8<A, B, C, D, E, F, G, H> = CompositeSymbol<[A, B, C, D, E, F, G, H]>;
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/Tuple.d.ts
|
|
36
|
+
declare class Tuple<A> extends Array<A> implements ArrayLike<A>, Iterable<A> {
|
|
37
|
+
[i: number]: A;
|
|
38
|
+
length: number;
|
|
39
|
+
/**
|
|
40
|
+
* @throws {TypeError} Will throw if called non-locally; use the tuple() method instead.
|
|
41
|
+
*/
|
|
42
|
+
constructor(iterable: Iterable<A>, confirm: typeof localToken);
|
|
43
|
+
/**
|
|
44
|
+
* Constructs a tuple.
|
|
45
|
+
*/
|
|
46
|
+
static tuple<const T extends readonly unknown[]>(...values: T): TupleN<T>;
|
|
47
|
+
static symbol<const T extends readonly unknown[]>(...values: T): CompositeSymbol<T>;
|
|
48
|
+
static unsafe(...values: unknown[]): unknown;
|
|
49
|
+
static unsafeSymbol(...values: unknown[]): unknown;
|
|
50
|
+
}
|
|
51
|
+
declare const localToken: unique symbol;
|
|
52
|
+
declare const tuple: typeof Tuple.tuple, symbol: typeof Tuple.symbol, unsafe: typeof Tuple.unsafe, unsafeSymbol: typeof Tuple.unsafeSymbol;
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/DeepCompositeSymbol.d.ts
|
|
55
|
+
/**
|
|
56
|
+
* Recursively creates a "composite key" (like a "value identity") for
|
|
57
|
+
* an object's entries (key-value pairs).
|
|
58
|
+
*/
|
|
59
|
+
declare const DeepCompositeSymbol: (object: object, filter?: (entry: [string, unknown]) => boolean) => unknown;
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/ValueObject.d.ts
|
|
62
|
+
type DeepReadonly<A> = { readonly [P in keyof A]: A[P] extends object ? DeepReadonly<A[P]> : A[P] };
|
|
63
|
+
/**
|
|
64
|
+
* Works somewhat similarly to Record in the Record & Tuple proposal:
|
|
65
|
+
* https://github.com/tc39/proposal-record-tuple
|
|
66
|
+
*/
|
|
67
|
+
declare function ValueObject<A extends object>(object: A, filter?: (entry: [string, unknown]) => boolean): DeepReadonly<A>;
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/memoize.d.ts
|
|
70
|
+
type Fn = (this: unknown, ...args: never[]) => unknown;
|
|
71
|
+
declare const memoize: <A extends Fn>(fn: A, cache?: WeakMap<object, unknown>) => A;
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/tuplerone.d.ts
|
|
74
|
+
/**
|
|
75
|
+
* A tuple whose members are allowed to all be primitive,
|
|
76
|
+
* so it can't be garbage-collected and should only be used
|
|
77
|
+
* in advanced contexts.
|
|
78
|
+
*/
|
|
79
|
+
declare const UnsafeTuple: typeof tuple;
|
|
80
|
+
declare const UnsafeCompositeSymbol: typeof tuple;
|
|
81
|
+
//#endregion
|
|
82
|
+
export { symbol as CompositeSymbol, type CompositeSymbol0, type CompositeSymbol1, type CompositeSymbol2, type CompositeSymbol3, type CompositeSymbol4, type CompositeSymbol5, type CompositeSymbol6, type CompositeSymbol7, type CompositeSymbol8, type CompositeSymbol as CompositeSymbolType, DeepCompositeSymbol, tuple as Tuple, type Tuple0, type Tuple1, type Tuple2, type Tuple3, type Tuple4, type Tuple5, type Tuple6, type Tuple7, type Tuple8, type TupleN, UnsafeCompositeSymbol, UnsafeTuple, ValueObject, memoize };
|
|
83
|
+
//# sourceMappingURL=tuplerone.d.mts.map
|