tutuca 0.9.39 → 0.9.41
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/dist/tutuca-cli.js +92 -39
- package/dist/tutuca-dev.js +18 -0
- package/dist/tutuca-dev.min.js +1 -1
- package/package.json +6 -7
- package/skill/immutable-js/SKILL.md +79 -0
- package/skill/immutable-js/references/collection.md +346 -0
- package/skill/immutable-js/references/conversions.md +99 -0
- package/skill/immutable-js/references/deep-updates.md +172 -0
- package/skill/immutable-js/references/equality.md +95 -0
- package/skill/immutable-js/references/list.md +266 -0
- package/skill/immutable-js/references/map.md +300 -0
- package/skill/immutable-js/references/predicates.md +93 -0
- package/skill/immutable-js/references/range-repeat.md +55 -0
- package/skill/immutable-js/references/record.md +196 -0
- package/skill/immutable-js/references/seq.md +248 -0
- package/skill/immutable-js/references/set.md +270 -0
- package/skill/immutable-js/references/shallow-functional.md +99 -0
- package/skill/immutable-js/references/stack.md +210 -0
- package/skill/margaui/SKILL.md +101 -0
- package/skill/margaui/components/accordion.md +127 -0
- package/skill/margaui/components/alert.md +174 -0
- package/skill/margaui/components/avatar.md +220 -0
- package/skill/margaui/components/badge.md +193 -0
- package/skill/margaui/components/breadcrumbs.md +103 -0
- package/skill/margaui/components/button.md +322 -0
- package/skill/margaui/components/calendar.md +67 -0
- package/skill/margaui/components/card.md +373 -0
- package/skill/margaui/components/carousel.md +387 -0
- package/skill/margaui/components/chat.md +171 -0
- package/skill/margaui/components/checkbox.md +101 -0
- package/skill/margaui/components/collapse.md +172 -0
- package/skill/margaui/components/countdown.md +165 -0
- package/skill/margaui/components/diff.md +53 -0
- package/skill/margaui/components/divider.md +107 -0
- package/skill/margaui/components/dock.md +173 -0
- package/skill/margaui/components/drawer.md +184 -0
- package/skill/margaui/components/dropdown.md +388 -0
- package/skill/margaui/components/fab.md +346 -0
- package/skill/margaui/components/fieldset.md +88 -0
- package/skill/margaui/components/file-input.md +84 -0
- package/skill/margaui/components/filter.md +52 -0
- package/skill/margaui/components/footer.md +583 -0
- package/skill/margaui/components/hero.md +135 -0
- package/skill/margaui/components/hover-3d.md +129 -0
- package/skill/margaui/components/hover-gallery.md +49 -0
- package/skill/margaui/components/indicator.md +265 -0
- package/skill/margaui/components/input.md +389 -0
- package/skill/margaui/components/join.md +100 -0
- package/skill/margaui/components/kbd.md +127 -0
- package/skill/margaui/components/label.md +102 -0
- package/skill/margaui/components/link.md +96 -0
- package/skill/margaui/components/list.md +182 -0
- package/skill/margaui/components/loading.md +105 -0
- package/skill/margaui/components/mask.md +168 -0
- package/skill/margaui/components/menu.md +856 -0
- package/skill/margaui/components/mockup-browser.md +39 -0
- package/skill/margaui/components/mockup-code.md +81 -0
- package/skill/margaui/components/mockup-phone.md +39 -0
- package/skill/margaui/components/mockup-window.md +33 -0
- package/skill/margaui/components/modal.md +178 -0
- package/skill/margaui/components/navbar.md +282 -0
- package/skill/margaui/components/pagination.md +122 -0
- package/skill/margaui/components/progress.md +135 -0
- package/skill/margaui/components/radial-progress.md +67 -0
- package/skill/margaui/components/radio.md +133 -0
- package/skill/margaui/components/range.md +134 -0
- package/skill/margaui/components/rating.md +170 -0
- package/skill/margaui/components/select.md +225 -0
- package/skill/margaui/components/skeleton.md +64 -0
- package/skill/margaui/components/stack.md +142 -0
- package/skill/margaui/components/stat.md +254 -0
- package/skill/margaui/components/status.md +73 -0
- package/skill/margaui/components/steps.md +138 -0
- package/skill/margaui/components/swap.md +152 -0
- package/skill/margaui/components/tab.md +248 -0
- package/skill/margaui/components/table.md +1018 -0
- package/skill/margaui/components/text-rotate.md +91 -0
- package/skill/margaui/components/textarea.md +85 -0
- package/skill/margaui/components/theme-controller.md +266 -0
- package/skill/margaui/components/timeline.md +1356 -0
- package/skill/margaui/components/toast.md +165 -0
- package/skill/margaui/components/toggle.md +135 -0
- package/skill/margaui/components/tooltip.md +181 -0
- package/skill/margaui/components/validator.md +163 -0
- package/skill/{advanced.md → tutuca/advanced.md} +5 -0
- package/skill/{cli.md → tutuca/cli.md} +17 -0
- package/skill/{core.md → tutuca/core.md} +5 -0
- /package/skill/{SKILL.md → tutuca/SKILL.md} +0 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
`Map` is an unordered keyed collection of (key, value) pairs with O(log32 N) gets and persistent sets, implemented as a hash-array mapped trie. Unlike the native `Map`, key equality is determined by `Immutable.is` (value equality), so any value — including `NaN` and other Immutable collections — may be used as a key. JavaScript objects used as keys still rely on strict identity. Use `OrderedMap` when iteration order must follow insertion order; it shares Map's full API but is slower and uses more memory.
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
import { Map, OrderedMap, List } from 'immutable';
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
## Construction
|
|
8
|
+
|
|
9
|
+
### Map
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
Map<K, V>(collection?: Iterable<readonly [K, V]>): Map<K, V>
|
|
13
|
+
Map<V>(obj: { [key: string]: V }): Map<string, V>
|
|
14
|
+
Map<R extends { [key in PropertyKey]: unknown }>(obj: R): MapOf<R>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Factory function (no `new`). Accepts another keyed collection, an iterable of `[K, V]` tuples, or a plain object. When given an object literal, the inferred type is the precise `MapOf<R>` (per-key value types).
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
Map({ key: 'value' });
|
|
21
|
+
Map([['key', 'value']]);
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
JS object keys are always strings; Immutable Map keys are not coerced:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
const m = Map({ 1: 'one' });
|
|
28
|
+
m.get('1'); // => "one"
|
|
29
|
+
m.get(1); // => undefined
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Map.isMap
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
Map.isMap(maybeMap: unknown): maybeMap is Map<unknown, unknown>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Keys are compared by value
|
|
39
|
+
|
|
40
|
+
Any Immutable collection may be used as a key; equality is structural.
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
Map().set(List([1, 2]), 'x').get(List([1, 2])); // => 'x'
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Reading
|
|
47
|
+
|
|
48
|
+
### get / has / includes
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
get(key: K): V | undefined
|
|
52
|
+
get<NSV>(key: K, notSetValue: NSV): V | NSV
|
|
53
|
+
has(key: K): boolean
|
|
54
|
+
includes(value: V): boolean // alias: contains
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`includes` checks values using `Immutable.is`.
|
|
58
|
+
|
|
59
|
+
### first / last
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
first(): V | undefined
|
|
63
|
+
last(): V | undefined
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### find / findKey / findEntry
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
find(predicate: (value: V, key: K, iter: this) => boolean, context?: unknown): V | undefined
|
|
70
|
+
findKey(predicate: (value: V, key: K, iter: this) => boolean, context?: unknown): K | undefined
|
|
71
|
+
findEntry(predicate: (value: V, key: K, iter: this) => boolean, context?: unknown): [K, V] | undefined
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### keyOf / lastKeyOf
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
keyOf(searchValue: V): K | undefined
|
|
78
|
+
lastKeyOf(searchValue: V): K | undefined
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### size
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
readonly size: number
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Persistent changes
|
|
88
|
+
|
|
89
|
+
### set
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
set(key: K, value: V): Map<K, V>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Replaces the value if the key already exists. Safe in `withMutations`.
|
|
96
|
+
|
|
97
|
+
### delete (alias `remove`)
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
delete(key: K): Map<K, V>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### deleteAll (alias `removeAll`)
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
deleteAll(keys: Iterable<K>): this
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### clear
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
clear(): Map<K, V>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### update
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
update<R>(updater: (value: this) => R): R
|
|
119
|
+
update(key: K, updater: (value: V | undefined) => V | undefined): Map<K, V>
|
|
120
|
+
update(key: K, notSetValue: V, updater: (value: V) => V): Map<K, V>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Equivalent to `map.set(key, updater(map.get(key)))`. If the updater returns the same value, the original Map is returned. The no-key form chains a function over the whole Map.
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
Map({ key: 'value' }).update('key', v => v + v); // => Map { "key": "valuevalue" }
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### merge (alias `concat`) / mergeWith / mergeDeep / mergeDeepWith
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
merge(...collections): Map<K, V>
|
|
133
|
+
mergeWith(merger: (oldVal, newVal, key) => unknown, ...collections): Map<K, V>
|
|
134
|
+
mergeDeep(...collections): Map<K, V>
|
|
135
|
+
mergeDeepWith(merger: (oldVal, newVal, key) => unknown, ...collections): Map<K, V>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Shallow merges (`merge`/`mergeWith`) overwrite per key; deep variants recurse into compatible collections (keyed-with-keyed, indexed-with-indexed, set-with-set). Indexed/set collections at matching keys are combined via `concat`/`union` rather than recursed. See `deep-updates.md` for examples and gotchas.
|
|
139
|
+
|
|
140
|
+
## Deep persistent changes
|
|
141
|
+
|
|
142
|
+
### setIn
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
setIn(keyPath: Iterable<unknown>, value: unknown): Map<K, V>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Creates intermediate Maps for missing keys. Throws if a path segment exists but cannot be updated (e.g. a primitive or non-collection object). Plain JS objects/arrays nested inside are updated immutably.
|
|
149
|
+
|
|
150
|
+
### deleteIn (alias `removeIn`)
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
deleteIn(keyPath: Iterable<unknown>): Map<K, V>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### updateIn
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
updateIn(keyPath: Iterable<unknown>, notSetValue: unknown, updater: (value) => unknown): Map<K, V>
|
|
160
|
+
updateIn(keyPath: Iterable<unknown>, updater: (value) => unknown): Map<K, V>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Returns the same Map if the updater returns the same value. Missing path segments are created as Maps.
|
|
164
|
+
|
|
165
|
+
### mergeIn / mergeDeepIn
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
mergeIn(keyPath: Iterable<unknown>, ...collections: Array<unknown>): Map<K, V>
|
|
169
|
+
mergeDeepIn(keyPath: Iterable<unknown>, ...collections: Array<unknown>): Map<K, V>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Equivalent to `updateIn(keyPath, x => x.merge(...))` and `updateIn(keyPath, x => x.mergeDeep(...))`. See `deep-updates.md`.
|
|
173
|
+
|
|
174
|
+
## Sequence algorithms
|
|
175
|
+
|
|
176
|
+
### map / mapKeys / mapEntries
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
map<M>(mapper: (value: V, key: K, iter: this) => M, context?: unknown): Map<K, M>
|
|
180
|
+
mapKeys<M>(mapper: (key: K, value: V, iter: this) => M, context?: unknown): Map<M, V>
|
|
181
|
+
mapEntries<KM, VM>(
|
|
182
|
+
mapper: (entry: [K, V], index: number, iter: this) => [KM, VM] | undefined,
|
|
183
|
+
context?: unknown
|
|
184
|
+
): Map<KM, VM>
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
If `mapEntries` returns `undefined` for an entry, the entry is filtered out; it always returns a new instance.
|
|
188
|
+
|
|
189
|
+
### flatMap
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
flatMap<KM, VM>(
|
|
193
|
+
mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
|
|
194
|
+
context?: unknown
|
|
195
|
+
): Map<KM, VM>
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### filter / filterNot
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
filter(predicate: (value: V, key: K, iter: this) => boolean, context?: unknown): Map<K, V>
|
|
202
|
+
filterNot(predicate: (value: V, key: K, iter: this) => boolean, context?: unknown): this
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### flip / reverse
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
flip(): Map<V, K>
|
|
209
|
+
reverse(): this
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### sort / sortBy
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
sort(comparator?: Comparator<V>): this & OrderedMap<K, V>
|
|
216
|
+
sortBy<C>(
|
|
217
|
+
comparatorValueMapper: (value: V, key: K, iter: this) => C,
|
|
218
|
+
comparator?: (a: C, b: C) => number
|
|
219
|
+
): OrderedMap<K, V>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Both produce an `OrderedMap` (sort imposes order). Eager.
|
|
223
|
+
|
|
224
|
+
### groupBy
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
groupBy<G>(grouper: (value: V, key: K, iter: this) => G, context?: unknown): Map<G, this>
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### partition
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
partition(predicate: (value: V, key: K, iter: this) => boolean, context?: unknown): [Map<K, V>, Map<K, V>]
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### concat
|
|
237
|
+
|
|
238
|
+
Alias for `merge` — see Persistent changes.
|
|
239
|
+
|
|
240
|
+
## Conversion
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
toArray(): Array<V> | Array<[K, V]>
|
|
244
|
+
toObject(): { [key: string]: V } // shallow, string keys
|
|
245
|
+
toJS(): { [key in PropertyKey]: DeepCopy<V> } | Array<DeepCopy<V>> // deep, string keys
|
|
246
|
+
toJSON(): { [key in PropertyKey]: V } | Array<V> // shallow, no child conversion
|
|
247
|
+
toSeq(): Seq<K, V>
|
|
248
|
+
toKeyedSeq(): Seq.Keyed<K, V>
|
|
249
|
+
asMutable(): this
|
|
250
|
+
asImmutable(): this
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
`asMutable` always returns `this`; do not use mutable copies for equality. See `conversions.md`.
|
|
254
|
+
|
|
255
|
+
## Mutation batching
|
|
256
|
+
|
|
257
|
+
### withMutations
|
|
258
|
+
|
|
259
|
+
```ts
|
|
260
|
+
withMutations(mutator: (mutable: this) => unknown): Map<K, V>
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Applies a batch of mutations to a temporary mutable copy, producing a single new immutable Map. Only methods documented as safe in `withMutations` (most setters/updaters) may be used inside.
|
|
264
|
+
|
|
265
|
+
```ts
|
|
266
|
+
Map().withMutations(m => { m.set('a', 1).set('b', 2).set('c', 3); });
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### wasAltered
|
|
270
|
+
|
|
271
|
+
```ts
|
|
272
|
+
wasAltered(): boolean
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
True if this is a mutable copy (`asMutable`) that has been mutated.
|
|
276
|
+
|
|
277
|
+
## OrderedMap
|
|
278
|
+
|
|
279
|
+
`OrderedMap` has the same API as `Map` but iterates in insertion order. Setting an existing key keeps its original position rather than moving it to the end. It is more expensive than `Map` (`set` is amortized O(log32 N) but not stable) and uses more memory.
|
|
280
|
+
|
|
281
|
+
```ts
|
|
282
|
+
OrderedMap<K, V>(collection?: Iterable<[K, V]>): OrderedMap<K, V>
|
|
283
|
+
OrderedMap<V>(obj: { [key: string]: V }): OrderedMap<string, V>
|
|
284
|
+
|
|
285
|
+
OrderedMap.isOrderedMap(maybeOrderedMap): maybeOrderedMap is OrderedMap<unknown, unknown>
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
```ts
|
|
289
|
+
Map({ a: 1, c: 3, b: 2 }); // iteration order undefined (often a, b, c)
|
|
290
|
+
OrderedMap({ a: 1, c: 3, b: 2 }); // iterates a, c, b
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
`sort` and `sortBy` on a `Map` always return an `OrderedMap`.
|
|
294
|
+
|
|
295
|
+
## See also
|
|
296
|
+
|
|
297
|
+
- `collection.md` — `Collection.Keyed` shared API (`reduce`, `every`, `some`, `count`, `slice`, etc.)
|
|
298
|
+
- `deep-updates.md` — patterns for `setIn`/`updateIn`/`mergeDeep`
|
|
299
|
+
- `conversions.md` — `toJS`/`toJSON`/`asMutable`/`asImmutable` semantics
|
|
300
|
+
- `predicates.md` — `isMap`, `isOrderedMap`, `isKeyed`
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
All `is*()` helpers are exported directly from `immutable` and most are TypeScript type guards (return `value is List<T>` etc.), so they narrow types in branches. Reach for them when accepting unknown input — typical entry-point checks after `fromJS()`, in serialization boundaries, or when an API accepts both Immutable and plain JS values.
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
import { isList, isMap, isCollection, isImmutable } from 'immutable';
|
|
5
|
+
|
|
6
|
+
function size(x: unknown): number {
|
|
7
|
+
if (isCollection(x) || isImmutable(x)) return x.size;
|
|
8
|
+
return 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function asEntries(x: unknown) {
|
|
12
|
+
if (isKeyed(x)) return x.entrySeq(); // [k, v] pairs
|
|
13
|
+
if (isIndexed(x)) return x.map((v, i) => [i, v]);
|
|
14
|
+
return Seq.Keyed();
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The concrete predicates are also re-exposed as static methods on their constructors (`List.isList`, `Map.isMap`, `Seq.isSeq`, etc.) — identical behavior, pick whichever reads better at the call site.
|
|
19
|
+
|
|
20
|
+
## Concrete-type predicates
|
|
21
|
+
|
|
22
|
+
- `isList(v): v is List<unknown>`
|
|
23
|
+
- `isMap(v): v is Map<unknown, unknown>` — also `true` for `OrderedMap`. Use `isOrderedMap` to distinguish.
|
|
24
|
+
- `isOrderedMap(v): v is OrderedMap<unknown, unknown>`
|
|
25
|
+
- `isSet(v): v is Set<unknown>` — also `true` for `OrderedSet`. Use `isOrderedSet` to distinguish.
|
|
26
|
+
- `isOrderedSet(v): v is OrderedSet<unknown>`
|
|
27
|
+
- `isStack(v): v is Stack<unknown>`
|
|
28
|
+
- `isRecord(v): v is Record<object>` — Records are not Collections; `isCollection(record)` is `false`.
|
|
29
|
+
- `isSeq(v): v is Seq.Indexed | Seq.Keyed | Seq.Set` — true for any lazy `Seq` subtype. Also exposed as `Seq.isSeq`.
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
isMap(Map()) // true
|
|
33
|
+
isMap(OrderedMap()) // true
|
|
34
|
+
isOrderedMap(Map()) // false
|
|
35
|
+
isOrderedMap(OrderedMap()) // true
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Shape predicates
|
|
39
|
+
|
|
40
|
+
Describe the role a value plays in iteration rather than its concrete class.
|
|
41
|
+
|
|
42
|
+
- `isCollection(v): v is Collection<unknown, unknown>` — true for any Immutable collection (`List`, `Map`, `Set`, `Stack`, `Seq`, etc.). False for `Record`.
|
|
43
|
+
- `isKeyed(v): v is Collection.Keyed<unknown, unknown>` — true for keyed collections (`Map`, `OrderedMap`, `Record`, `Seq.Keyed`); they iterate as `[k, v]` entries.
|
|
44
|
+
- `isIndexed(v): v is Collection.Indexed<unknown>` — true for ordered indexed collections (`List`, `Stack`, `Seq.Indexed`); iterate by integer index.
|
|
45
|
+
- `isAssociative(v): v is Collection.Keyed | Collection.Indexed` — true if the collection supports `get(key)` lookup, i.e. keyed OR indexed (everything except `Set`/`OrderedSet`/`Seq.Set`).
|
|
46
|
+
- `isOrdered(v): v is OrderedCollection<unknown>` — true if iteration order is stable (`List`, `Stack`, `OrderedMap`, `OrderedSet`, `Seq.Indexed`, etc.). False for unsorted `Map`/`Set`.
|
|
47
|
+
|
|
48
|
+
## isImmutable
|
|
49
|
+
|
|
50
|
+
- `isImmutable(v): v is Collection<unknown, unknown>`
|
|
51
|
+
- True for any Immutable collection or `Record`. Effectively `isCollection(v) || isRecord(v)` — the one-stop check for "did this come from Immutable.js?". Still returns `true` mid-`withMutations()`.
|
|
52
|
+
|
|
53
|
+
## Quick reference matrix
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
isCollection isKeyed isIndexed isAssociative isOrdered isImmutable
|
|
57
|
+
List yes yes yes yes yes
|
|
58
|
+
Map yes yes yes yes
|
|
59
|
+
OrderedMap yes yes yes yes yes
|
|
60
|
+
Set yes yes
|
|
61
|
+
OrderedSet yes yes yes
|
|
62
|
+
Stack yes yes yes yes yes
|
|
63
|
+
Record no yes yes yes
|
|
64
|
+
Seq.Keyed yes yes yes yes
|
|
65
|
+
Seq.Indexed yes yes yes yes yes
|
|
66
|
+
Seq.Set yes yes
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Notes:
|
|
70
|
+
- `isOrdered` is unrelated to `Seq.Keyed` ordering: a `Seq.Keyed` built from an array of pairs will not pass `isOrdered` — only `OrderedMap` does for keyed shapes.
|
|
71
|
+
- `isCollection` is `false` for `Record` even though `isImmutable` is `true`.
|
|
72
|
+
- All concrete `is*` predicates imply `isCollection` except `isRecord`.
|
|
73
|
+
- `isMap`/`isSet` are union checks; prefer `isOrderedMap`/`isOrderedSet` when iteration order matters.
|
|
74
|
+
|
|
75
|
+
## Common patterns
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
// Idempotent fromJS-style normalization
|
|
79
|
+
const toMap = (v: unknown) => isMap(v) ? v : Map(v as any);
|
|
80
|
+
|
|
81
|
+
// Generic deep walker that handles plain JS and Immutable inputs
|
|
82
|
+
function walk(v: unknown, fn: (leaf: unknown) => void): void {
|
|
83
|
+
if (isKeyed(v)) v.forEach(child => walk(child, fn));
|
|
84
|
+
else if (isIndexed(v)) v.forEach(child => walk(child, fn));
|
|
85
|
+
else fn(v);
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## See also
|
|
90
|
+
|
|
91
|
+
- `list.md`, `map.md`, `set.md`, `stack.md`, `record.md`, `seq.md`
|
|
92
|
+
- `equality.md` — `is()` / `isValueObject()` for value equality
|
|
93
|
+
- `conversions.md` — `fromJS()` / `toJS()` boundaries where these checks are most useful
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
`Range()` and `Repeat()` are factory functions (no `new`) that produce a lazy `Seq.Indexed`. They are cheap to construct, can represent infinite sequences, and compose with every `Seq` method (`map`, `filter`, `take`, `slice`, `concat`, `reduce`, ...). Nothing is computed until the sequence is iterated or materialized via `toArray`/`toList`/etc.
|
|
2
|
+
|
|
3
|
+
## Range
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
Range(start?: number, end?: number, step?: number): Seq.Indexed<number>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
- `start` defaults to `0` (inclusive).
|
|
10
|
+
- `end` defaults to `Infinity` (exclusive). When `end` is `Infinity`, you MUST bound the sequence with `take()` / `takeWhile()` / `slice()` before materializing, or iteration will never terminate.
|
|
11
|
+
- `step` defaults to `1`. May be negative to count down. When `start === end`, the range is empty.
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
Range(0, 5).toArray(); // => [0, 1, 2, 3, 4]
|
|
15
|
+
Range(10, 30, 5).toArray(); // => [10, 15, 20, 25]
|
|
16
|
+
Range(30, 10, -5).toArray(); // => [30, 25, 20, 15]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Repeat
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
Repeat<T>(value: T, times?: number): Seq.Indexed<T>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- `times` defaults to `Infinity`. Same rule as `Range`: bound infinite repeats with `take()`/`slice()` before materializing.
|
|
26
|
+
- `value` is held by reference; `Repeat` does not clone it.
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
Repeat('x', 3).toArray(); // => ['x', 'x', 'x']
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Common patterns
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
// Squares of 0..9 as a List
|
|
36
|
+
Range(0, 10).map(n => n * n).toList();
|
|
37
|
+
// => List [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
|
|
38
|
+
|
|
39
|
+
// Concatenate two finite repeats
|
|
40
|
+
Repeat('a', 3).concat(Repeat('b', 2)).toArray();
|
|
41
|
+
// => ['a', 'a', 'a', 'b', 'b']
|
|
42
|
+
|
|
43
|
+
// Bound an infinite Range with take()
|
|
44
|
+
Range().filter(n => n % 7 === 0).take(5).toArray();
|
|
45
|
+
// => [0, 7, 14, 21, 28]
|
|
46
|
+
|
|
47
|
+
// Build a List directly from a Range
|
|
48
|
+
List(Range(0, 5)); // => List [0, 1, 2, 3, 4]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## See also
|
|
52
|
+
|
|
53
|
+
- `seq.md` — the underlying lazy `Seq.Indexed` API and laziness rules.
|
|
54
|
+
- `list.md` — materializing into a `List` (e.g. `List(Range(0, 5))`).
|
|
55
|
+
- `conversions.md` — `toArray`, `toList`, `toSet`, and other terminal operations.
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
`Record` creates a class-like factory with a known shape and a default value for each key. Instances are immutable, compare by value with `.equals()`, and expose direct property access (`record.foo`) in addition to `.get('foo')`. Use a Record when modeling a "thing with a known set of fields" rather than a free-form `Map`. Records always have a value for the keys they define; setting an unknown key throws, and `delete` resets the key to its default rather than removing it. Record instances are also `Map`-like via `getIn`/`setIn`, `toSeq`, and iteration over `[key, value]` pairs.
|
|
2
|
+
|
|
3
|
+
## Defining a Record class
|
|
4
|
+
|
|
5
|
+
`Record(defaultValues, name?)` returns a `Record.Factory`. The optional `name` is used in `toString()` output and error messages.
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
import { Record } from 'immutable';
|
|
9
|
+
|
|
10
|
+
const Point = Record({ x: 0, y: 0 }, 'Point');
|
|
11
|
+
const p = Point({ x: 3 });
|
|
12
|
+
p.x; // 3 (direct property access)
|
|
13
|
+
p.get('y'); // 0 (default)
|
|
14
|
+
p.toString(); // 'Point { "x": 3, "y": 0 }'
|
|
15
|
+
|
|
16
|
+
Point({ x: 1, z: 9 }).get('z'); // undefined — undeclared keys are ignored
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
A Record class can be subclassed to add methods (instances must then be created with `new`):
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
class ABRecord extends Record({ a: 1, b: 2 }) {
|
|
23
|
+
getAB() { return this.a + this.b; }
|
|
24
|
+
}
|
|
25
|
+
new ABRecord({ b: 3 }).getAB(); // 4
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Record.Factory (the constructor)
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
Record.Factory<TProps>(values?: Partial<TProps>): RecordOf<TProps>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Calling the factory creates an instance; calling with no argument yields all defaults. The factory is `instanceof`-compatible with the instances it produces.
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
const Point = Record({ x: 0, y: 0 }, 'Point');
|
|
38
|
+
Point(); // all defaults
|
|
39
|
+
Point({ x: 3 }) instanceof Point; // true
|
|
40
|
+
Point.displayName; // 'Point'
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Record.isRecord
|
|
44
|
+
```ts
|
|
45
|
+
Record.isRecord(maybeRecord: unknown): boolean
|
|
46
|
+
```
|
|
47
|
+
True if the argument is any Record instance.
|
|
48
|
+
|
|
49
|
+
### Record.getDescriptiveName
|
|
50
|
+
```ts
|
|
51
|
+
Record.getDescriptiveName(record: RecordOf<TProps>): string
|
|
52
|
+
```
|
|
53
|
+
Returns the `name` passed to `Record(values, name)`, or `"Record"` if none was provided.
|
|
54
|
+
|
|
55
|
+
## Instance: Reading
|
|
56
|
+
|
|
57
|
+
### get
|
|
58
|
+
```ts
|
|
59
|
+
get<K>(key: K): TProps[K]
|
|
60
|
+
get<T>(key: string, notSetValue: T): T
|
|
61
|
+
```
|
|
62
|
+
Returns the value for `key`, or the declared default. Direct property access (`record.field`) reads the same value.
|
|
63
|
+
|
|
64
|
+
### has
|
|
65
|
+
```ts
|
|
66
|
+
has(key: string): boolean
|
|
67
|
+
```
|
|
68
|
+
True when `key` is one of the declared fields.
|
|
69
|
+
|
|
70
|
+
### hasIn / getIn
|
|
71
|
+
```ts
|
|
72
|
+
hasIn(keyPath: Iterable<unknown>): boolean
|
|
73
|
+
getIn(keyPath: Iterable<unknown>): unknown
|
|
74
|
+
```
|
|
75
|
+
Deep lookup along a key path through nested collections.
|
|
76
|
+
|
|
77
|
+
### equals
|
|
78
|
+
```ts
|
|
79
|
+
equals(other: unknown): boolean
|
|
80
|
+
```
|
|
81
|
+
Value equality: same Record factory and equal values for every declared key.
|
|
82
|
+
|
|
83
|
+
### hashCode
|
|
84
|
+
```ts
|
|
85
|
+
hashCode(): number
|
|
86
|
+
```
|
|
87
|
+
Hash consistent with `equals`, suitable for use as a `Map` key or `Set` member.
|
|
88
|
+
|
|
89
|
+
### toSeq
|
|
90
|
+
```ts
|
|
91
|
+
toSeq(): Seq.Keyed<keyof TProps, TProps[keyof TProps]>
|
|
92
|
+
```
|
|
93
|
+
Keyed Seq view of the record's fields. Records are also iterable as `[key, value]` pairs.
|
|
94
|
+
|
|
95
|
+
### toJS / toJSON / toObject
|
|
96
|
+
```ts
|
|
97
|
+
toJS(): DeepCopy<TProps> // deep, recursively converts nested Immutable values
|
|
98
|
+
toJSON(): TProps // shallow plain object
|
|
99
|
+
toObject(): TProps // shallow plain object
|
|
100
|
+
```
|
|
101
|
+
`toJS` may not be overridden; override `toJSON` for custom serialization.
|
|
102
|
+
|
|
103
|
+
## Instance: Persistent changes
|
|
104
|
+
|
|
105
|
+
All persistent updates return a new Record of the same type. Setting or deleting a key not in the defaults throws.
|
|
106
|
+
|
|
107
|
+
### set
|
|
108
|
+
```ts
|
|
109
|
+
set<K>(key: K, value: TProps[K]): this
|
|
110
|
+
```
|
|
111
|
+
```js
|
|
112
|
+
Point({ x: 3 }).set('y', 4); // Point { x: 3, y: 4 }
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### delete (alias remove)
|
|
116
|
+
```ts
|
|
117
|
+
delete<K>(key: K): this
|
|
118
|
+
```
|
|
119
|
+
Resets the key to its declared default — does not remove it from the shape.
|
|
120
|
+
|
|
121
|
+
### clear
|
|
122
|
+
```ts
|
|
123
|
+
clear(): this
|
|
124
|
+
```
|
|
125
|
+
Returns an instance with every field reset to its default.
|
|
126
|
+
|
|
127
|
+
### update
|
|
128
|
+
```ts
|
|
129
|
+
update<K>(key: K, updater: (value: TProps[K]) => TProps[K]): this
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### merge / mergeDeep / mergeWith / mergeDeepWith
|
|
133
|
+
```ts
|
|
134
|
+
merge(...collections: Array<Partial<TProps>>): this
|
|
135
|
+
mergeDeep(...collections: Array<Partial<TProps>>): this
|
|
136
|
+
mergeWith(merger, ...collections): this
|
|
137
|
+
mergeDeepWith(merger, ...collections): this
|
|
138
|
+
```
|
|
139
|
+
`merge` shallowly applies provided fields; `mergeDeep` recurses into nested Immutable values. The `*With` variants resolve conflicts via the supplied merger.
|
|
140
|
+
|
|
141
|
+
### setIn / deleteIn / updateIn / mergeIn / mergeDeepIn
|
|
142
|
+
```ts
|
|
143
|
+
setIn(keyPath, value): this
|
|
144
|
+
deleteIn(keyPath): this // alias removeIn
|
|
145
|
+
updateIn(keyPath, updater): this
|
|
146
|
+
mergeIn(keyPath, ...collections): this
|
|
147
|
+
mergeDeepIn(keyPath, ...collections): this
|
|
148
|
+
```
|
|
149
|
+
Deep variants that follow `keyPath` into nested collections.
|
|
150
|
+
|
|
151
|
+
### withMutations / asMutable / asImmutable / wasAltered
|
|
152
|
+
```ts
|
|
153
|
+
withMutations(mutator: (mutable: this) => unknown): this
|
|
154
|
+
asMutable(): this
|
|
155
|
+
asImmutable(): this
|
|
156
|
+
wasAltered(): boolean
|
|
157
|
+
```
|
|
158
|
+
Transient batching, mirroring `Map`. Only `set` may be used mutatively inside `withMutations`.
|
|
159
|
+
|
|
160
|
+
## TypeScript notes
|
|
161
|
+
|
|
162
|
+
Use `RecordFactory<TProps>` for the factory type and `RecordOf<TProps>` for instances. `RecordOf<T>` is `Record<T> & Readonly<T>`, which is what enables typed property access.
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
import { Record, type RecordFactory, type RecordOf } from 'immutable';
|
|
166
|
+
|
|
167
|
+
type Point3DProps = { x: number; y: number; z: number };
|
|
168
|
+
const defaults: Point3DProps = { x: 0, y: 0, z: 0 };
|
|
169
|
+
|
|
170
|
+
const makePoint3D: RecordFactory<Point3DProps> = Record(defaults);
|
|
171
|
+
export type Point3D = RecordOf<Point3DProps>;
|
|
172
|
+
const p: Point3D = makePoint3D({ x: 10, y: 20, z: 30 });
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
When subclassing, do **not** use `RecordFactory`; apply the props type when extending instead:
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
class Person extends Record({ name: 'Aristotle', age: 2400 })<{ name: string; age: number }> {
|
|
179
|
+
getName(): string { return this.get('name'); }
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Gotchas
|
|
184
|
+
|
|
185
|
+
- Defaults are fixed at factory creation. New keys cannot be added later — `set`/`delete` of an unknown key throws.
|
|
186
|
+
- `delete(key)` resets to the default; it does not remove the field from the shape.
|
|
187
|
+
- `clear()` returns the all-defaults instance, not an empty one.
|
|
188
|
+
- Records from different factories are never `equals`, even when they hold the same values.
|
|
189
|
+
- Direct assignment (`record.field = ...`) throws; use `set`. Property access (`record.field`) is unsupported on IE8 — fall back to `get('field')` if targeting it.
|
|
190
|
+
- `toJS` is final and cannot be overridden; override `toJSON` for custom serialization.
|
|
191
|
+
|
|
192
|
+
## See also
|
|
193
|
+
|
|
194
|
+
- `map.md` — when keys are dynamic or the shape isn't known up front.
|
|
195
|
+
- `equality.md` — how `equals`/`hashCode` interact with Record identity.
|
|
196
|
+
- `predicates.md` — `isRecord` and related type guards.
|