@chzky/core
v2.0.0
Published
[](https://jsr.io/@chzky/core)
Readme
@chzky/core
@chzky/core 是一个受 Rust、Haskell 和其他函数式编程语言启发的 TypeScript/JavaScript 实用工具库。它提供了类型安全的数据结构、函数式编程工具和强大的错误处理机制。
安装
# Deno
deno add jsr:@chzky/core
# npm / pnpm / yarn
npm install @chzky/core
pnpm add @chzky/core
yarn add @chzky/core核心特性
- Monad 类型:
Result<T, E>、Option<T>、Either<L, R>、Shunt<T>等函数式数据结构 - 强大的错误处理:
AnyError基类及丰富的预定义错误类型,支持装饰器快速创建自定义错误 - 函数式工具:柯里化、管道、流控制、匹配模式、记忆化等
- Zod 集成:与 Zod schema 验证库的深度集成
- TypeScript 优先:完整的类型推导和类型安全
快速开始
Result - 错误处理
Result<T, E> 用于显式处理可能失败的操作,替代 try/catch。
import { Ok, Err, result } from '@chzky/core'
// 创建 Result
const success = Ok(42)
const failure = Err(new Error('something went wrong'))
// 使用 result 包装可能抛出异常的函数
const parseJSON = result((str: string) => JSON.parse(str))
parseJSON('{"a":1}') // Ok({ a: 1 })
parseJSON('invalid') // Err(SyntaxError...)Ok
表示成功的结果,包含值 T。
| 方法 | 说明 |
|:---|:---|
| unwrap() | 获取内部值,失败时抛出 |
| expect(err) | 获取内部值,失败时抛出自定义错误 |
| unwrap_or(def) | 获取内部值,或使用默认值 |
| map(fn) | 成功时转换值 |
| and_then(fn) | 成功时链式调用另一个返回 Result 的函数 |
| match(ok, err) | 模式匹配处理两种状态 |
Err
表示失败的结果,包含错误 E。
| 方法 | 说明 |
|:---|:---|
| unwrap_err() | 获取内部错误 |
| map_err(fn) | 转换错误类型 |
| or(res) | 失败时返回另一个 Result |
| or_else(fn) | 失败时计算替代结果 |
Option - 空值处理
Option<T> 用于处理可能不存在的值,替代 null/undefined。
import { Some, None, option } from '@chzky/core'
// 创建 Option
const some = Some('value')
const none = None
// 从可能为空的值创建
const opt1 = option(maybeNull) // null/undefined -> None, 其他 -> Some
// 便捷构造
const fromStr = option.from_str('') // None (空字符串)
const fromNum = option.from_num(NaN) // None (NaN)| 方法 | 说明 |
|:---|:---|
| is_some / is_none | 类型判断 |
| unwrap() | 获取值,None 时抛出 NoneError |
| unwrap_or(def) | 获取值或默认值 |
| unwrap_or_else(fn) | 获取值或计算默认值 |
| map(fn) | 有值时转换 |
| and_then(fn) | 有值时链式调用 |
| filter(fn) | 条件过滤 |
| flatten() | 展平嵌套 Option |
Either - 互斥选择
Either<L, R> 表示"要么是 L,要么是 R",常用于错误处理或分支逻辑。
import { Left, Right, either } from '@chzky/core'
// 使用构造函数
const left: Either<string, number> = Left('error')
const right: Either<string, number> = Right(42)
// 使用 either 辅助函数
const result = either((l, r) => {
if (Math.random() > 0.5) l('left value')
else r('right value')
})| 方法 | 说明 |
|:---|:---|
| is_left() / is_right() | 判断左右 |
| unwrap_left() / unwrap_right() | 解包(错误方向会抛异常) |
| unwrap_lor(or) / unwrap_ror(or) | 带默认值的解包 |
| exchange() | 左右互换 |
| match(left, right) | 模式匹配 |
Shunt - 流程控制
Shunt<T> 用于管道中的流程控制,Mainstream 继续执行,Reflux 提前返回。
import { Mainstream, Reflux, shunt, pipe } from '@chzky/core'
const process = pipe.sync(
(x: number) => x > 0 ? Mainstream(x * 2) : Reflux('negative'),
(x) => x + 1, // 仅 Mainstream 会执行
(x) => String(x)
)
process(5) // "11"
process(-1) // "negative"AnyError - 错误系统
统一的错误基类,支持级别分类和美观的日志输出。
import { AnyError, AnyErr, panic, todo } from '@chzky/core'
// 创建错误
const err = new AnyError('Error', '连接失败', 'NetworkError')
// 快速创建并包装为 Err
const result = AnyErr('Error', '连接失败', 'NetworkError')
// 直接抛出致命错误
panic('Fatal', '系统崩溃', 'SystemPanic')
// TODO 占位
todo('实现用户认证模块')错误级别:Debug | Info | Warn | Error | Fatal | Panic | Unknow
预定义错误类型
| 类别 | 错误类型 |
|:---|:---|
| Debug | MockError |
| Info | NaNError, TodoError |
| Warn | CheckingError |
| Error | AbortedError, AlreadyExistsError, BadResourceError, DuplicateError, HttpError (含完整 HTTP 状态码), IllegalExpressionError, IndexOutOfBoundsError, LogicError, MultipleError, NoneError, NotFoundError, NotImplementsError, NotSupportError, PermissionError, ReadOnlyError, SerializeError, TimedOutError, TransformError, UsedError, WriteZeroError |
| Fatal | IllegalOperatError |
| Unknow | AnyHowError, UnexpectedError |
自定义错误(装饰器)
import { ErrorMachine } from '@chzky/core'
@ErrorMachine('MyError', 'Error', '默认错误信息')
class MyError extends AnyErrorMachine {}
const err = MyError.new('具体原因')State - 状态管理
State<Main, Effect> 封装主值和副作用,便于状态追踪。
import { State } from '@chzky/core'
const state = State('view', { count: 0 })
state.unwrap() // 'view' (主值)
state.effect() // { count: 0 }
// 转换
const next = state.map(mode => mode === 'view' ? 'edit' : 'view')
// 配合 match.when_state 使用
match(state)
.when_state('view', () => renderView())
.when_state('edit', (effect) => renderEdit(effect))
.done()Refer - 响应式引用
简单的可观察引用,支持监听变化。
import { Refer } from '@chzky/core'
const ref = Refer(0)
ref.watch((newVal, oldVal) => {
console.log(`${oldVal} -> ${newVal}`)
})
ref.value = 10 // 触发监听: 0 -> 10
ref.update(20) // 同上Pipe & Flow - 管道组合
import { pipe, flow, lzpipe } from '@chzky/core'
// pipe: 立即执行
const result = pipe.sync(
5,
x => x * 2,
x => x + 1,
String // "11"
)
// flow: 创建可复用的管道函数
const doubleThenString = flow.sync(
(x: number) => x * 2,
String
)
doubleThenString(5) // "10"
// lzpipe: 惰性求值(延迟执行)
const lazy = lzpipe.sync(
() => expensiveOp1(),
() => expensiveOp2()
)
// 此时还未执行
const result = lazy() // 现在执行Match - 模式匹配
强大的模式匹配,替代复杂的 if/else 或 switch。
import { match, functor, $0, $1 } from '@chzky/core'
const result = match(value)
.case(200, 'ok')
.case(404, 'not found')
.when(v => v >= 500, () => 'server error')
.some([100, 101], 'continue') // 多个条件满足其一
.every([isAuth, isAdmin], 'admin') // 多个条件需全部满足
.done('unknown') // 默认值
// 使用 functor 进行表达式匹配
match(user)
.case(functor`${$0.age} >= 18`, 'adult')
.done()
// 重新匹配(rematch)
match(complexValue)
.when(isTypeA, transformA)
.rematch() // 用 transformA 的结果继续匹配
.when(isTypeB, transformB)
.done()函数式工具
柯里化 (Curry)
import { curry } from '@chzky/core'
const add = (a: number, b: number, c: number) => a + b + c
const curried = curry(add, 3)
curried(1)(2)(3) // 6
// 自动柯里化
const auto = curry.auto(add, 3)
auto(1, 2)(3) // 6
// 逆序参数
const rev = curry.reverse(add, 3)
rev(3)(2)(1) // 6 (1+2+3)记忆化 (Memo)
import { memo } from '@chzky/core'
const fib = memo((n: number): number => {
return n < 2 ? n : fib(n - 1) + fib(n - 2)
})
fib(100) // 极速计算,自动缓存
// 使用 Symbol.dispose 清理
{
using _ = fib
// 作用域结束自动清理缓存
}其他工具
| 函数 | 说明 |
|:---|:---|
| defer(deferFn, runFn) | try-finally 模式 |
| IIFE(fn) | 立即执行函数 |
| overload() | 函数重载 |
| onion_compose(...middleware) | Koa 风格的洋葱模型中间件 |
| Using(disposeFn) / Using(value, disposeFn) | RAII 资源管理 |
| Future(promise) | 链式调用 Promise |
Zod 集成
与 Zod schema 验证深度集成,支持自定义类型。
import { z } from '@chzky/core/zod'
// Option 验证
const schema = z.option(z.string())
// Result 验证
const resultSchema = z.result(z.number(), z.anyerr(MyError))
// Either 验证
const eitherSchema = z.either(z.string(), z.number())
// Shunt 验证
const shuntSchema = z.shunt(z.string(), z.number())
// 类型转换辅助
const asNumber = z.as.number('42') // 42
const parsed = z.as.json('{"a":1}') // Result<{a: number}, SerializeError>
// 验证函数
const check = z.checking(z.object({ name: z.string() }))
check({ name: 'test' }) // Ok(...)
check({}) // Err(CheckingError)
// 多模式验证
z.checking.or([pattern1, pattern2])
z.checking.and([pattern1, pattern2])
// 数据变形
const morph = z.morphs(
z.string(), // 输入
(s) => s.length, // 转换
z.number() // 输出
)类型接口 (TypeClass)
库中实现了多种 Haskell/Rust 风格的类型类接口:
| 接口 | 方法 | 说明 |
|:---|:---|:---|
| Copy | clone() | 可复制 |
| Default | default() | 默认值 |
| PartialEq | eq(other) | 部分相等比较 |
| Equal | equals(other) | 深度相等比较 |
| Ord | compare(other) | 全序比较 |
| Debug | log() | 调试输出 |
| As | as(flag) | 类型转换 |
| Try | spread(), [SYMBOL_BRANCH]() | 可分支计算 |
| Serialize | serialize(), deserialize() | 序列化 |
| SemiGroup | concat(other) | 半群操作 |
检查实现:
import { implements_copy, implements_ord, /* ... */ } from '@chzky/core'
if (implements_copy(value)) {
const copy = value.clone()
}更多 API
完整 API 文档请参考:JSR 文档
