happy-rusty 1.10.0 → 1.10.1
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/CHANGELOG.md +72 -0
- package/README.cn.md +28 -24
- package/README.md +27 -23
- package/dist/{main.cjs → mod.cjs} +148 -57
- package/dist/mod.cjs.map +1 -0
- package/dist/mod.d.cts +5132 -0
- package/dist/mod.d.mts +5132 -0
- package/dist/{main.mjs → mod.mjs} +148 -57
- package/dist/mod.mjs.map +1 -0
- package/package.json +28 -28
- package/dist/main.cjs.map +0 -1
- package/dist/main.mjs.map +0 -1
- package/dist/types.d.ts +0 -5204
package/CHANGELOG.md
CHANGED
|
@@ -5,55 +5,83 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.10.1] - 2026-09-06
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **Channel**: `for await` leaving early (a `break`, an error thrown in the loop body, or an explicit `iterator.return()`) now cancels the pending `next()`. An abandoned iterator no longer holds its spot in the receive queue, so it cannot swallow a message intended for another consumer
|
|
13
|
+
- **Channel**: a timeout callback firing after its waiter was already served no longer removes an unrelated waiter (`splice(-1, 1)` on a `-1` index)
|
|
14
|
+
- **OnceAsync**: `set()` and `tryInsert()` return `Err` while a `getOrInit`/`getOrTryInit` attempt is in flight, instead of reporting `Ok` and then being overwritten by the attempt's result — matching Rust's `OnceLock::set` racing an in-progress `get_or_init`
|
|
15
|
+
- **OnceAsync**: `wait()` no longer rejects when an initialization attempt fails. It keeps waiting until the cell is actually initialized, matching Rust's `OnceLock::wait`
|
|
16
|
+
- **OnceAsync**: a caller joining a failed attempt retries with its own initializer, matching Rust's `get_or_try_init`. The in-flight slot is claimed synchronously, so a synchronously-executing initializer that re-enters joins the attempt instead of starting a second one
|
|
17
|
+
|
|
18
|
+
### Chores
|
|
19
|
+
|
|
20
|
+
- Migrated to the Vite+ unified toolchain (`vp check` for fmt + lint + type checking, `vp pack` for JS and `.d.ts` bundling), replacing ESLint and the previous build setup
|
|
21
|
+
- Merged all CI gates into a single `ci.yml` job and added attw + publint verification of the tarball that is actually published
|
|
22
|
+
- Upgraded devDependencies: `vite-plus` 0.3.0, `@vitest/coverage-v8` 4.1.11, `publint` 0.3.24
|
|
23
|
+
|
|
8
24
|
## [1.10.0] - 2026-06-30
|
|
9
25
|
|
|
10
26
|
### Added
|
|
27
|
+
|
|
11
28
|
- **New Sync Primitive**: `Semaphore` - Counting semaphore for limiting async concurrency, with `acquire`/`tryAcquire`/`withPermit`/`availablePermits`. Inspired by tokio's `Semaphore` (Rust std does not include one). Useful for fetch rate limiting, connection pools, and task queues.
|
|
12
29
|
- **New Method**: `RwLockWriteGuard.downgrade()` - Atomically converts a write guard to a read guard, releasing waiting readers while keeping pending writers waiting. Equivalent to Rust 1.92's `RwLockWriteGuard::downgrade`
|
|
13
30
|
|
|
14
31
|
### Chores
|
|
32
|
+
|
|
15
33
|
- Upgraded devDependencies: vite, vitest, @vitest/coverage-v8, @vitest/ui, eslint, rollup, typescript-eslint
|
|
16
34
|
|
|
17
35
|
## [1.9.2] - 2026-04-12
|
|
18
36
|
|
|
19
37
|
### Changed
|
|
38
|
+
|
|
20
39
|
- **Performance**: Added `/*#__PURE__*/` annotations to all top-level function call expressions for better tree-shaking support in consumer bundlers
|
|
21
40
|
|
|
22
41
|
### Fixed
|
|
42
|
+
|
|
23
43
|
- **Build**: Migrated `treeshake` config from deprecated `'smallest'` string to object form for Vite 8 (Rolldown) compatibility
|
|
24
44
|
- **Build**: Added `topLevelVar: false` to output options to preserve `const` declarations in bundled output
|
|
25
45
|
|
|
26
46
|
### Chores
|
|
47
|
+
|
|
27
48
|
- Upgraded devDependencies: vite, vitest, eslint, typedoc, typescript-eslint
|
|
28
49
|
|
|
29
50
|
## [1.9.1] - 2026-01-16
|
|
30
51
|
|
|
31
52
|
### Changed
|
|
53
|
+
|
|
32
54
|
- **Performance**: `Channel` buffer replaced `Array` with `Queue` for O(1) shift operations
|
|
33
55
|
|
|
34
56
|
### Documentation
|
|
57
|
+
|
|
35
58
|
- Added `@since` tags to all public APIs
|
|
36
59
|
- Improved JSDoc consistency and formatting
|
|
37
60
|
|
|
38
61
|
### CI
|
|
62
|
+
|
|
39
63
|
- Changed JSR publish to trigger on release instead of push to main
|
|
40
64
|
|
|
41
65
|
## [1.9.0] - 2026-01-04
|
|
42
66
|
|
|
43
67
|
### Added
|
|
68
|
+
|
|
44
69
|
- **Try Extensions for Result**:
|
|
45
70
|
- `andTryAsync<U>` - Like `andThenAsync`, but auto-catches exceptions/Promise rejections and converts them to `Err`
|
|
46
71
|
- `orTryAsync<F>` - Like `orElseAsync`, but auto-catches exceptions in recovery logic
|
|
47
72
|
|
|
48
73
|
### Changed
|
|
74
|
+
|
|
49
75
|
- **Performance**: `map()` and `mapErr()` now return `this` when the Result variant doesn't match, avoiding unnecessary object creation
|
|
50
76
|
|
|
51
77
|
### Removed
|
|
78
|
+
|
|
52
79
|
- `promiseToAsyncResult()` - Use `tryAsyncResult()` instead (deprecated since v1.7.0)
|
|
53
80
|
|
|
54
81
|
## [1.8.0] - 2025-12-31
|
|
55
82
|
|
|
56
83
|
### Added
|
|
84
|
+
|
|
57
85
|
- **New Sync Primitives**:
|
|
58
86
|
- `OnceAsync<T>` - Async-first one-time initialization with concurrent call handling
|
|
59
87
|
- `RwLock<T>` - Async read-write lock (multiple concurrent readers or single writer)
|
|
@@ -78,18 +106,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
78
106
|
- **Rust Documentation Links** - All Rust-equivalent interfaces now link to official Rust docs via `@see` tags
|
|
79
107
|
|
|
80
108
|
### Changed
|
|
109
|
+
|
|
81
110
|
- **Module Reorganization** - Source code restructured into `core/` (Option, Result) and `std/` (sync, ops) directories, mirroring Rust's stdlib organization
|
|
82
111
|
- **Async Callback Types** - All async methods now accept `PromiseLike<T> | T` instead of just `Promise<T>`, allowing mixed sync/async callbacks
|
|
83
112
|
- **Async Return Types** - Use `Awaited<T>` to properly flatten nested Promises in async method return types
|
|
84
113
|
- **Internal Optimizations** - Cached Promise constants (`ASYNC_NONE`, etc.) for better runtime performance
|
|
85
114
|
|
|
86
115
|
### Fixed
|
|
116
|
+
|
|
87
117
|
- `this` binding issue in `Once.getOrTryInitAsync`
|
|
88
118
|
- Nested Promise flattening in async methods
|
|
89
119
|
|
|
90
120
|
## [1.7.1] - 2025-12-26
|
|
91
121
|
|
|
92
122
|
### Added
|
|
123
|
+
|
|
93
124
|
- **Argument passing** - All `try*` functions now support passing arguments like `Promise.try`:
|
|
94
125
|
- `tryOption(JSON.parse, jsonString)` instead of `tryOption(() => JSON.parse(jsonString))`
|
|
95
126
|
- `tryResult(decodeURIComponent, str)` instead of `tryResult(() => decodeURIComponent(str))`
|
|
@@ -98,35 +129,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
98
129
|
## [1.7.0] - 2025-12-26
|
|
99
130
|
|
|
100
131
|
### Added
|
|
132
|
+
|
|
101
133
|
- `tryOption()` - Capture synchronous exceptions as Option (success → Some, exception → None)
|
|
102
134
|
- `tryAsyncOption()` - Capture async/Promise exceptions as Option
|
|
103
135
|
- `tryResult()` - Capture synchronous exceptions as Result (success → Ok, exception → Err)
|
|
104
136
|
- `tryAsyncResult()` - Capture async/Promise exceptions as Result
|
|
105
137
|
|
|
106
138
|
### Deprecated
|
|
139
|
+
|
|
107
140
|
- `promiseToAsyncResult()` - Use `tryAsyncResult()` instead (same functionality, more consistent naming)
|
|
108
141
|
|
|
109
142
|
## [1.6.2] - 2025-12-25
|
|
110
143
|
|
|
111
144
|
### Changed
|
|
145
|
+
|
|
112
146
|
- `promiseToAsyncResult` now accepts `PromiseLike<T>` instead of `Promise<T>` for broader compatibility with thenable objects
|
|
113
147
|
- Use `AsyncResult` type alias in function signatures for consistency
|
|
114
148
|
|
|
115
149
|
### Removed
|
|
150
|
+
|
|
116
151
|
- Removed unused `source` field from package.json (Parcel legacy)
|
|
117
152
|
- Removed redundant `@internal` tags from private (non-exported) functions
|
|
118
153
|
|
|
119
154
|
## [1.6.1] - 2025-12-19
|
|
120
155
|
|
|
121
156
|
### Changed
|
|
157
|
+
|
|
122
158
|
- License changed from GPL-3.0 to MIT for broader adoption and easier integration
|
|
123
159
|
|
|
124
160
|
### Added
|
|
161
|
+
|
|
125
162
|
- Navigation links (GitHub, npm, JSR) in TypeDoc documentation header
|
|
126
163
|
|
|
127
164
|
## [1.6.0] - 2025-12-18
|
|
128
165
|
|
|
129
166
|
### Added
|
|
167
|
+
|
|
130
168
|
- **Sync Primitives**: `Once<T>`, `Lazy<T>`, `LazyAsync<T>`, `Mutex<T>` for Rust-style synchronization
|
|
131
169
|
- **Control Flow**: `ControlFlow<B, C>` with `Break` and `Continue` variants
|
|
132
170
|
- `Symbol.toStringTag` property to all types for better type identification
|
|
@@ -140,28 +178,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
140
178
|
- CHANGELOG.md with full version history
|
|
141
179
|
|
|
142
180
|
### Changed
|
|
181
|
+
|
|
143
182
|
- All instances are now frozen with `Object.freeze()` for runtime immutability
|
|
144
183
|
- TypeDoc output format from Markdown to HTML for GitHub Pages compatibility
|
|
145
184
|
- Migrated from Deno test to Vitest
|
|
146
185
|
- Build process split into Vite (JS) and Rollup (dts)
|
|
147
186
|
|
|
148
187
|
### Fixed
|
|
188
|
+
|
|
149
189
|
- Symbol property syntax and duplicate declaration issues
|
|
150
190
|
- Type inference improvements for `None` interface methods
|
|
151
191
|
|
|
152
192
|
## [1.5.0] - 2024-08-11
|
|
153
193
|
|
|
154
194
|
### Added
|
|
195
|
+
|
|
155
196
|
- Async versions of methods: `isSomeAndAsync`, `isOkAndAsync`, `isErrAndAsync`, `unwrapOrElseAsync`, `andThenAsync`, `orElseAsync`
|
|
156
197
|
- Async examples
|
|
157
198
|
|
|
158
199
|
### Changed
|
|
200
|
+
|
|
159
201
|
- Updated pnpm to v9.7.0
|
|
160
202
|
- Updated ESLint configuration
|
|
161
203
|
|
|
162
204
|
## [1.4.0] - 2024-08-05
|
|
163
205
|
|
|
164
206
|
### Added
|
|
207
|
+
|
|
165
208
|
- `Ok()` constructor without arguments (similar to Rust's `Ok(())`)
|
|
166
209
|
- `RESULT_VOID` constant for void Result returns
|
|
167
210
|
- `VoidResult<E>`, `VoidIOResult`, `AsyncVoidResult<E>`, `AsyncVoidIOResult` type aliases
|
|
@@ -169,94 +212,114 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
169
212
|
## [1.3.2] - 2024-08-04
|
|
170
213
|
|
|
171
214
|
### Changed
|
|
215
|
+
|
|
172
216
|
- Renamed `helpers` to `utils`
|
|
173
217
|
- Improved `@example` annotations in JSDoc
|
|
174
218
|
|
|
175
219
|
## [1.3.1] - 2024-08-03
|
|
176
220
|
|
|
177
221
|
### Fixed
|
|
222
|
+
|
|
178
223
|
- `map` methods now correctly return new objects instead of mutating
|
|
179
224
|
|
|
180
225
|
### Changed
|
|
226
|
+
|
|
181
227
|
- Updated Rollup to v4.20.0
|
|
182
228
|
|
|
183
229
|
## [1.3.0] - 2024-08-01
|
|
184
230
|
|
|
185
231
|
### Added
|
|
232
|
+
|
|
186
233
|
- `RESULT_TRUE`, `RESULT_FALSE`, `RESULT_ZERO` constants
|
|
187
234
|
|
|
188
235
|
### Fixed
|
|
236
|
+
|
|
189
237
|
- Circular dependency issues
|
|
190
238
|
|
|
191
239
|
### Changed
|
|
240
|
+
|
|
192
241
|
- Reorganized code structure
|
|
193
242
|
|
|
194
243
|
## [1.2.0] - 2024-08-01
|
|
195
244
|
|
|
196
245
|
### Added
|
|
246
|
+
|
|
197
247
|
- `isOption()` and `isResult()` type guard utilities
|
|
198
248
|
- Custom string conversion for Option and Result
|
|
199
249
|
|
|
200
250
|
### Changed
|
|
251
|
+
|
|
201
252
|
- Replaced arrow functions with normal functions for better debug experience
|
|
202
253
|
- Updated ESLint to v9
|
|
203
254
|
|
|
204
255
|
## [1.1.2] - 2024-07-17
|
|
205
256
|
|
|
206
257
|
### Added
|
|
258
|
+
|
|
207
259
|
- `asOk<F>()` and `asErr<U>()` methods for type casting
|
|
208
260
|
|
|
209
261
|
## [1.1.1] - 2024-07-13
|
|
210
262
|
|
|
211
263
|
### Fixed
|
|
264
|
+
|
|
212
265
|
- TypeDoc configuration issues
|
|
213
266
|
|
|
214
267
|
### Changed
|
|
268
|
+
|
|
215
269
|
- Updated dependencies
|
|
216
270
|
|
|
217
271
|
## [1.1.0] - 2024-06-09
|
|
218
272
|
|
|
219
273
|
### Added
|
|
274
|
+
|
|
220
275
|
- `Option.filter()` method
|
|
221
276
|
- Many new Option and Result APIs
|
|
222
277
|
- Comprehensive code comments and documentation
|
|
223
278
|
|
|
224
279
|
### Changed
|
|
280
|
+
|
|
225
281
|
- Improved type inference
|
|
226
282
|
- `Option.filter()` now returns `Option<T>` instead of boolean
|
|
227
283
|
|
|
228
284
|
## [1.0.9] - 2024-05-14
|
|
229
285
|
|
|
230
286
|
### Added
|
|
287
|
+
|
|
231
288
|
- Documentation for exported symbols
|
|
232
289
|
- README examples
|
|
233
290
|
|
|
234
291
|
## [1.0.8] - 2024-05-13
|
|
235
292
|
|
|
236
293
|
### Changed
|
|
294
|
+
|
|
237
295
|
- Switched from npm to pnpm
|
|
238
296
|
- Added GitHub Actions test workflow with Codecov
|
|
239
297
|
|
|
240
298
|
## [1.0.7] - 2024-05-08
|
|
241
299
|
|
|
242
300
|
### Changed
|
|
301
|
+
|
|
243
302
|
- `Some` value type changed to `NonNullable<T>`
|
|
244
303
|
|
|
245
304
|
### Fixed
|
|
305
|
+
|
|
246
306
|
- Can now invoke `err()` from `Ok` variant
|
|
247
307
|
|
|
248
308
|
## [1.0.6] - 2024-05-08
|
|
249
309
|
|
|
250
310
|
### Added
|
|
311
|
+
|
|
251
312
|
- Commonly used type exports
|
|
252
313
|
|
|
253
314
|
### Changed
|
|
315
|
+
|
|
254
316
|
- Set `type: "module"` in package.json
|
|
255
317
|
- Build target set to ESNext
|
|
256
318
|
|
|
257
319
|
## [1.0.5] - 2024-05-05
|
|
258
320
|
|
|
259
321
|
### Changed
|
|
322
|
+
|
|
260
323
|
- Throw `TypeError` instead of generic `Error`
|
|
261
324
|
- Switched to Rollup for building
|
|
262
325
|
- Added Bun support in CI
|
|
@@ -264,45 +327,54 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
264
327
|
## [1.0.4] - 2024-05-04
|
|
265
328
|
|
|
266
329
|
### Added
|
|
330
|
+
|
|
267
331
|
- Chinese README (`README.cn.md`)
|
|
268
332
|
- JSR publishing workflow
|
|
269
333
|
- npm publishing workflows
|
|
270
334
|
|
|
271
335
|
### Changed
|
|
336
|
+
|
|
272
337
|
- Replaced Parcel with Rollup for building
|
|
273
338
|
- Replaced Jest with Bun test
|
|
274
339
|
|
|
275
340
|
## [1.0.3] - 2024-04-27
|
|
276
341
|
|
|
277
342
|
### Added
|
|
343
|
+
|
|
278
344
|
- Installation and Examples sections in README
|
|
279
345
|
|
|
280
346
|
### Changed
|
|
347
|
+
|
|
281
348
|
- Force return const for better type inference
|
|
282
349
|
|
|
283
350
|
## [1.0.2] - 2024-04-26
|
|
284
351
|
|
|
285
352
|
### Added
|
|
353
|
+
|
|
286
354
|
- JSR publishing support
|
|
287
355
|
|
|
288
356
|
### Changed
|
|
357
|
+
|
|
289
358
|
- Improved code comments
|
|
290
359
|
|
|
291
360
|
## [1.0.1] - 2024-04-26
|
|
292
361
|
|
|
293
362
|
### Changed
|
|
363
|
+
|
|
294
364
|
- Replaced enum with const for better tree-shaking
|
|
295
365
|
- Marked package as side-effect free
|
|
296
366
|
|
|
297
367
|
## [1.0.0] - 2024-04-24
|
|
298
368
|
|
|
299
369
|
### Added
|
|
370
|
+
|
|
300
371
|
- Initial release
|
|
301
372
|
- `Option<T>` type with `Some` and `None` variants
|
|
302
373
|
- `Result<T, E>` type with `Ok` and `Err` variants
|
|
303
374
|
- Full TypeScript support
|
|
304
375
|
- Comprehensive API matching Rust's Option and Result
|
|
305
376
|
|
|
377
|
+
[1.10.1]: https://github.com/JiangJie/happy-rusty/compare/v1.10.0...v1.10.1
|
|
306
378
|
[1.10.0]: https://github.com/JiangJie/happy-rusty/compare/v1.9.2...v1.10.0
|
|
307
379
|
[1.9.2]: https://github.com/JiangJie/happy-rusty/compare/v1.9.1...v1.9.2
|
|
308
380
|
[1.9.1]: https://github.com/JiangJie/happy-rusty/compare/v1.9.0...v1.9.1
|
package/README.cn.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# happy-rusty
|
|
2
2
|
|
|
3
3
|
[](LICENSE)
|
|
4
|
-
[](https://github.com/JiangJie/happy-rusty/actions/workflows/ci.yml)
|
|
5
5
|
[](https://codecov.io/gh/JiangJie/happy-rusty)
|
|
6
6
|
[](https://npmjs.org/package/happy-rusty)
|
|
7
7
|
[](https://npmjs.org/package/happy-rusty)
|
|
@@ -84,37 +84,39 @@ const config = parseJSON<Config>(jsonStr)
|
|
|
84
84
|
|
|
85
85
|
### Option<T>
|
|
86
86
|
|
|
87
|
-
| 分类
|
|
88
|
-
|
|
89
|
-
| **构造器**
|
|
90
|
-
| **查询**
|
|
91
|
-
| **提取**
|
|
92
|
-
| **转换**
|
|
93
|
-
| **布尔操作** | `and(other)`, `andThen(fn)`, `or(other)`, `orElse(fn)`, `xor(other)`
|
|
94
|
-
| **类型转换** | `okOr(err)`, `okOrElse(fn)`, `transpose()`
|
|
95
|
-
| **组合**
|
|
96
|
-
| **副作用**
|
|
97
|
-
| **比较**
|
|
87
|
+
| 分类 | 方法 |
|
|
88
|
+
| ------------ | -------------------------------------------------------------------------------------- |
|
|
89
|
+
| **构造器** | `Some(value)`, `None` |
|
|
90
|
+
| **查询** | `isSome()`, `isNone()`, `isSomeAnd(fn)` |
|
|
91
|
+
| **提取** | `expect(msg)`, `unwrap()`, `unwrapOr(default)`, `unwrapOrElse(fn)` |
|
|
92
|
+
| **转换** | `map(fn)`, `mapOr(default, fn)`, `mapOrElse(defaultFn, fn)`, `filter(fn)`, `flatten()` |
|
|
93
|
+
| **布尔操作** | `and(other)`, `andThen(fn)`, `or(other)`, `orElse(fn)`, `xor(other)` |
|
|
94
|
+
| **类型转换** | `okOr(err)`, `okOrElse(fn)`, `transpose()` |
|
|
95
|
+
| **组合** | `zip(other)`, `zipWith(other, fn)`, `unzip()` |
|
|
96
|
+
| **副作用** | `inspect(fn)` |
|
|
97
|
+
| **比较** | `eq(other)` |
|
|
98
98
|
|
|
99
99
|
### Result<T, E>
|
|
100
100
|
|
|
101
|
-
| 分类
|
|
102
|
-
|
|
103
|
-
| **构造器**
|
|
104
|
-
| **查询**
|
|
105
|
-
| **提取 Ok**
|
|
106
|
-
| **提取 Err** | `expectErr(msg)`, `unwrapErr()`
|
|
107
|
-
| **转换**
|
|
108
|
-
| **布尔操作** | `and(other)`, `andThen(fn)`, `or(other)`, `orElse(fn)`
|
|
109
|
-
| **类型转换** | `ok()`, `err()`, `transpose()`
|
|
110
|
-
| **类型断言** | `asOk<F>()`, `asErr<U>()`
|
|
111
|
-
| **副作用**
|
|
112
|
-
| **比较**
|
|
101
|
+
| 分类 | 方法 |
|
|
102
|
+
| ------------ | -------------------------------------------------------------------------------------- |
|
|
103
|
+
| **构造器** | `Ok(value)`, `Ok()` (void), `Err(error)` |
|
|
104
|
+
| **查询** | `isOk()`, `isErr()`, `isOkAnd(fn)`, `isErrAnd(fn)` |
|
|
105
|
+
| **提取 Ok** | `expect(msg)`, `unwrap()`, `unwrapOr(default)`, `unwrapOrElse(fn)` |
|
|
106
|
+
| **提取 Err** | `expectErr(msg)`, `unwrapErr()` |
|
|
107
|
+
| **转换** | `map(fn)`, `mapErr(fn)`, `mapOr(default, fn)`, `mapOrElse(defaultFn, fn)`, `flatten()` |
|
|
108
|
+
| **布尔操作** | `and(other)`, `andThen(fn)`, `or(other)`, `orElse(fn)` |
|
|
109
|
+
| **类型转换** | `ok()`, `err()`, `transpose()` |
|
|
110
|
+
| **类型断言** | `asOk<F>()`, `asErr<U>()` |
|
|
111
|
+
| **副作用** | `inspect(fn)`, `inspectErr(fn)` |
|
|
112
|
+
| **比较** | `eq(other)` |
|
|
113
113
|
|
|
114
114
|
### 异步方法
|
|
115
115
|
|
|
116
116
|
所有转换方法都有带 `Async` 后缀的异步变体(如 `andThenAsync`、`mapAsync`、`unwrapOrElseAsync`)。
|
|
117
117
|
|
|
118
|
+
异步变体遵循库的错误约定:回调被实际调用时,若其同步抛错,错误会在调用点同步抛出——与同步方法一致;只有回调返回 rejected Promise 时,错误才以 rejection 形式呈现。如需把抛出的异常转为 `Err`/`None` 值,请使用 `try*` 辅助函数(`tryResult`/`tryAsyncResult`/`tryOption`/`tryAsyncOption`),或在 `Result` 上使用 `andTryAsync`/`orTryAsync` 方法。
|
|
119
|
+
|
|
118
120
|
### 类型别名
|
|
119
121
|
|
|
120
122
|
```ts
|
|
@@ -195,12 +197,14 @@ some.unwrap = () => 0; // TypeError: Cannot assign to read only property
|
|
|
195
197
|
## 为什么选择 happy-rusty?
|
|
196
198
|
|
|
197
199
|
JavaScript 的 `null`/`undefined` 和 try-catch 模式会导致:
|
|
200
|
+
|
|
198
201
|
- 未捕获的空引用错误
|
|
199
202
|
- 遗忘的错误处理
|
|
200
203
|
- 冗长的 try-catch 代码块
|
|
201
204
|
- 不清晰的函数契约
|
|
202
205
|
|
|
203
206
|
`happy-rusty` 提供了 Rust 久经考验的模式:
|
|
207
|
+
|
|
204
208
|
- **显式可选性** - `Option<T>` 在类型中明确表示值的缺失
|
|
205
209
|
- **显式错误** - `Result<T, E>` 强制考虑错误处理
|
|
206
210
|
- **链式调用** - 无需嵌套 if-else 或 try-catch 即可转换值
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# happy-rusty
|
|
2
2
|
|
|
3
3
|
[](LICENSE)
|
|
4
|
-
[](https://github.com/JiangJie/happy-rusty/actions/workflows/ci.yml)
|
|
5
5
|
[](https://codecov.io/gh/JiangJie/happy-rusty)
|
|
6
6
|
[](https://npmjs.org/package/happy-rusty)
|
|
7
7
|
[](https://npmjs.org/package/happy-rusty)
|
|
@@ -84,37 +84,39 @@ const config = parseJSON<Config>(jsonStr)
|
|
|
84
84
|
|
|
85
85
|
### Option<T>
|
|
86
86
|
|
|
87
|
-
| Category
|
|
88
|
-
|
|
89
|
-
| **Constructors** | `Some(value)`, `None`
|
|
90
|
-
| **Querying**
|
|
91
|
-
| **Extracting**
|
|
87
|
+
| Category | Methods |
|
|
88
|
+
| ---------------- | -------------------------------------------------------------------------------------- |
|
|
89
|
+
| **Constructors** | `Some(value)`, `None` |
|
|
90
|
+
| **Querying** | `isSome()`, `isNone()`, `isSomeAnd(fn)` |
|
|
91
|
+
| **Extracting** | `expect(msg)`, `unwrap()`, `unwrapOr(default)`, `unwrapOrElse(fn)` |
|
|
92
92
|
| **Transforming** | `map(fn)`, `mapOr(default, fn)`, `mapOrElse(defaultFn, fn)`, `filter(fn)`, `flatten()` |
|
|
93
|
-
| **Boolean ops**
|
|
94
|
-
| **Converting**
|
|
95
|
-
| **Combining**
|
|
96
|
-
| **Side effects** | `inspect(fn)`
|
|
97
|
-
| **Comparison**
|
|
93
|
+
| **Boolean ops** | `and(other)`, `andThen(fn)`, `or(other)`, `orElse(fn)`, `xor(other)` |
|
|
94
|
+
| **Converting** | `okOr(err)`, `okOrElse(fn)`, `transpose()` |
|
|
95
|
+
| **Combining** | `zip(other)`, `zipWith(other, fn)`, `unzip()` |
|
|
96
|
+
| **Side effects** | `inspect(fn)` |
|
|
97
|
+
| **Comparison** | `eq(other)` |
|
|
98
98
|
|
|
99
99
|
### Result<T, E>
|
|
100
100
|
|
|
101
|
-
| Category
|
|
102
|
-
|
|
103
|
-
| **Constructors**
|
|
104
|
-
| **Querying**
|
|
105
|
-
| **Extracting Ok**
|
|
106
|
-
| **Extracting Err** | `expectErr(msg)`, `unwrapErr()`
|
|
107
|
-
| **Transforming**
|
|
108
|
-
| **Boolean ops**
|
|
109
|
-
| **Converting**
|
|
110
|
-
| **Type casting**
|
|
111
|
-
| **Side effects**
|
|
112
|
-
| **Comparison**
|
|
101
|
+
| Category | Methods |
|
|
102
|
+
| ------------------ | -------------------------------------------------------------------------------------- |
|
|
103
|
+
| **Constructors** | `Ok(value)`, `Ok()` (void), `Err(error)` |
|
|
104
|
+
| **Querying** | `isOk()`, `isErr()`, `isOkAnd(fn)`, `isErrAnd(fn)` |
|
|
105
|
+
| **Extracting Ok** | `expect(msg)`, `unwrap()`, `unwrapOr(default)`, `unwrapOrElse(fn)` |
|
|
106
|
+
| **Extracting Err** | `expectErr(msg)`, `unwrapErr()` |
|
|
107
|
+
| **Transforming** | `map(fn)`, `mapErr(fn)`, `mapOr(default, fn)`, `mapOrElse(defaultFn, fn)`, `flatten()` |
|
|
108
|
+
| **Boolean ops** | `and(other)`, `andThen(fn)`, `or(other)`, `orElse(fn)` |
|
|
109
|
+
| **Converting** | `ok()`, `err()`, `transpose()` |
|
|
110
|
+
| **Type casting** | `asOk<F>()`, `asErr<U>()` |
|
|
111
|
+
| **Side effects** | `inspect(fn)`, `inspectErr(fn)` |
|
|
112
|
+
| **Comparison** | `eq(other)` |
|
|
113
113
|
|
|
114
114
|
### Async Methods
|
|
115
115
|
|
|
116
116
|
All transformation methods have async variants with `Async` suffix (e.g., `andThenAsync`, `mapAsync`, `unwrapOrElseAsync`).
|
|
117
117
|
|
|
118
|
+
Async variants follow the library's error convention: when the callback is invoked, a synchronous throw propagates synchronously at the call site — just like the sync methods — and only a callback that returns a rejected promise surfaces as a promise rejection. To capture thrown exceptions as `Err`/`None` values instead, use the `try*` helpers (`tryResult`/`tryAsyncResult`/`tryOption`/`tryAsyncOption`) or, on `Result`, the `andTryAsync`/`orTryAsync` methods.
|
|
119
|
+
|
|
118
120
|
### Type Aliases
|
|
119
121
|
|
|
120
122
|
```ts
|
|
@@ -200,12 +202,14 @@ We intentionally omit `readonly` modifiers from method signatures in interfaces.
|
|
|
200
202
|
## Why happy-rusty?
|
|
201
203
|
|
|
202
204
|
JavaScript's `null`/`undefined` and try-catch patterns lead to:
|
|
205
|
+
|
|
203
206
|
- Uncaught null reference errors
|
|
204
207
|
- Forgotten error handling
|
|
205
208
|
- Verbose try-catch blocks
|
|
206
209
|
- Unclear function contracts
|
|
207
210
|
|
|
208
211
|
`happy-rusty` provides Rust's battle-tested patterns:
|
|
212
|
+
|
|
209
213
|
- **Explicit optionality** - `Option<T>` makes absence visible in types
|
|
210
214
|
- **Explicit errors** - `Result<T, E>` forces error handling consideration
|
|
211
215
|
- **Method chaining** - Transform values without nested if-else or try-catch
|