@codehz/json-expr 0.4.0 → 0.5.0

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 CHANGED
@@ -13,6 +13,9 @@
13
13
  - 🧩 **可组合** - 表达式可以相互组合,形成复杂的计算树
14
14
  - 🔄 **短路求值** - 支持 `&&`、`||`、`??` 和三元表达式的控制流优化
15
15
  - 📝 **内联优化** - 自动内联只被引用一次的子表达式
16
+ - 🔗 **Proxy 变量系统** - 支持链式属性访问和方法调用,如 `config.timeout`、`user.profile.name`
17
+ - 🎛️ **Lambda 表达式** - 类型安全的数组方法支持(map、filter、reduce 等)
18
+ - 🛡️ **错误检测** - 编译时检测未定义变量和类型错误
16
19
 
17
20
  ## 快速开始
18
21
 
@@ -25,7 +28,7 @@ bun install @codehz/json-expr
25
28
  ### 基本用法
26
29
 
27
30
  ```typescript
28
- import { variable, expr, compile, evaluate } from "@codehz/json-expr";
31
+ import { variable, expr, compile, evaluate, t, lambda } from "@codehz/json-expr";
29
32
 
30
33
  // 定义类型化变量(使用 TypeScript 泛型)
31
34
  const x = variable<number>();
@@ -43,6 +46,14 @@ const compiled = compile(result, { x, y });
43
46
  // 执行编译后的表达式
44
47
  const value = evaluate(compiled, { x: 2, y: 3 });
45
48
  // => 11 (2+3 + 2*3 = 5 + 6 = 11)
49
+
50
+ // 使用模板字符串
51
+ const name = variable<string>();
52
+ const greeting = t`Hello, ${name}!`;
53
+
54
+ // 使用 lambda 表达式
55
+ const numbers = variable<number[]>();
56
+ const doubled = numbers.map(lambda<[number], number>((n) => expr({ n })("n * 2")));
46
57
  ```
47
58
 
48
59
  ## 核心概念
@@ -215,8 +226,126 @@ const result = evaluate(compiled, { name: "Alice" });
215
226
  // => "Hello, Alice!"
216
227
  ```
217
228
 
229
+ ### `lambda<Args, R>(builder: LambdaBuilder<Args, R>): Lambda<Args, R>`
230
+
231
+ 创建类型安全的 lambda 表达式,用于数组方法(map、filter、reduce 等)。
232
+
233
+ **参数:**
234
+
235
+ - `builder` - Lambda 构建函数,接收参数代理,返回函数体表达式
236
+
237
+ **返回值:** Lambda 表达式,可在数组方法中使用
238
+
239
+ **示例:**
240
+
241
+ ```typescript
242
+ import { lambda } from "@codehz/json-expr";
243
+
244
+ // 单参数 lambda
245
+ const numbers = variable<number[]>();
246
+ const doubled = numbers.map(lambda<[number], number>((n) => expr({ n })("n * 2")));
247
+
248
+ const compiled = compile(doubled, { numbers });
249
+ const result = evaluate(compiled, { numbers: [1, 2, 3] });
250
+ // => [2, 4, 6]
251
+
252
+ // 多参数 lambda(reduce)
253
+ const sum = numbers.reduce(
254
+ lambda<[number, number], number>((acc, val) => expr({ acc, val })("acc + val")),
255
+ 0
256
+ );
257
+
258
+ // 捕获外部变量
259
+ const multiplier = variable<number>();
260
+ const scaled = numbers.map(lambda<[number], number>((n) => expr({ n, multiplier })("n * multiplier")));
261
+ ```
262
+
218
263
  ## 高级用法
219
264
 
265
+ ### Proxy 变量系统
266
+
267
+ `variable()` 创建的变量是 Proxy 对象,支持链式属性访问和方法调用,所有操作都会自动转换为表达式。
268
+
269
+ **属性访问:**
270
+
271
+ ```typescript
272
+ const config = variable<{
273
+ timeout: number;
274
+ retries: number;
275
+ database: {
276
+ host: string;
277
+ port: number;
278
+ };
279
+ }>();
280
+
281
+ // 链式属性访问
282
+ const timeout = config.timeout; // 自动转换为表达式
283
+ const dbHost = config.database.host; // 支持嵌套访问
284
+
285
+ const compiled = compile(timeout, { config });
286
+ const result = evaluate(compiled, {
287
+ config: { timeout: 5000, retries: 3, database: { host: "localhost", port: 5432 } },
288
+ });
289
+ // => 5000
290
+ ```
291
+
292
+ **方法调用:**
293
+
294
+ ```typescript
295
+ const calculator = variable<{
296
+ add(a: number, b: number): number;
297
+ multiply(x: number, y: number): number;
298
+ }>();
299
+
300
+ // 方法调用
301
+ const sum = calculator.add(1, 2);
302
+ const product = calculator.multiply(5, 3);
303
+
304
+ // 链式方法调用
305
+ const builder = variable<{
306
+ setName(name: string): typeof builder;
307
+ build(): { name: string };
308
+ }>();
309
+ const result = builder.setName("test").build();
310
+
311
+ // 编译并执行
312
+ const compiled = compile(sum, { calculator });
313
+ const value = evaluate(compiled, {
314
+ calculator: {
315
+ add: (a, b) => a + b,
316
+ multiply: (x, y) => x * y,
317
+ },
318
+ });
319
+ // => 3
320
+ ```
321
+
322
+ **数组方法:**
323
+
324
+ 数组变量支持所有标准数组方法,并自动处理类型推导:
325
+
326
+ ```typescript
327
+ const numbers = variable<number[]>();
328
+ const users = variable<{ id: number; name: string }[]>();
329
+
330
+ // map
331
+ const doubled = numbers.map((n) => expr({ n })("n * 2"));
332
+
333
+ // filter
334
+ const activeUsers = users.filter((u) => expr({ u })("u.active"));
335
+
336
+ // reduce
337
+ const sum = numbers.reduce(
338
+ lambda<[number, number], number>((acc, val) => expr({ acc, val })("acc + val")),
339
+ 0
340
+ );
341
+
342
+ // find, some, every, sort 等
343
+ const firstMatch = users.find((u) => expr({ u })("u.id === 1"));
344
+ const hasAdmins = users.some((u) => expr({ u })("u.role === 'admin'"));
345
+ const allActive = users.every((u) => expr({ u })("u.active"));
346
+ const sorted = numbers.toSorted(lambda<[number, number], number>((a, b) => expr({ a, b })("a - b")));
347
+ ```
348
+
220
349
  ### 内置全局对象
221
350
 
222
351
  表达式中可以直接使用以下内置对象(无需在上下文中定义):
@@ -235,6 +364,44 @@ const result = evaluate(compiled, { x: 16 });
235
364
  // => 4
236
365
  ```
237
366
 
367
+ ### 支持的运算符和语法
368
+
369
+ **算术运算符:**
370
+
371
+ - `+`, `-`, `*`, `/`, `%`, `**` (幂运算)
372
+
373
+ **比较运算符:**
374
+
375
+ - `==`, `===`, `!=`, `!==`, `<`, `>`, `<=`, `>=`
376
+
377
+ **逻辑运算符:**
378
+
379
+ - `&&`, `||`, `!`, `??` (空值合并)
380
+
381
+ **位运算符:**
382
+
383
+ - `&`, `|`, `^`, `~`, `<<`, `>>`, `>>>`
384
+
385
+ **其他运算符:**
386
+
387
+ - `? :` (三元表达式)
388
+ - `in` (属性存在检查)
389
+ - `instanceof` (类型检查)
390
+ - `typeof` (类型检测)
391
+ - `?.` (可选链)
392
+ - `?.()` (可选调用)
393
+ - `?.[]` (可选元素访问)
394
+
395
+ **语法特性:**
396
+
397
+ - 对象字面量:`{ key: value, ... }`
398
+ - 数组字面量:`[element1, element2, ...]`
399
+ - 箭头函数:`(param) => expression`
400
+ - 函数调用:`func(arg1, arg2, ...)`
401
+ - 成员访问:`obj.prop`, `obj["prop"]`, `arr[0]`
402
+ - 模板字面量(通过 `t` 标签函数)
403
+ - 分组括号:`(expression)`
404
+
238
405
  ### 条件表达式
239
406
 
240
407
  ```typescript
@@ -275,6 +442,75 @@ const result = evaluate(compiled, { a: 2, b: 3 });
275
442
  // => (2+3) * (2*3) - (2-3) = 5 * 6 - (-1) = 30 + 1 = 31
276
443
  ```
277
444
 
445
+ ### 短路求值(控制流优化)
446
+
447
+ 编译器支持为 `&&`、`||`、`??` 和三元表达式生成短路求值代码,避免不必要的计算:
448
+
449
+ ```typescript
450
+ const a = variable<boolean>();
451
+ const b = variable<boolean>();
452
+
453
+ // 逻辑或短路
454
+ const orExpr = expr({ a, b })("a || b");
455
+ const compiled = compile(orExpr, { a, b }, { shortCircuit: true });
456
+
457
+ // 当 a 为 true 时,b 不会被求值
458
+ // 编译数据包含控制流节点:
459
+ // [["a", "b"], ["br", "$0", 1], "$1", ["phi"]]
460
+
461
+ // 空值合并
462
+ const x = variable<number | null>();
463
+ const y = variable<number>();
464
+ const coalesce = expr({ x, y })("x ?? y");
465
+
466
+ // 三元表达式
467
+ const condition = variable<boolean>();
468
+ const result = variable<number>();
469
+ const alternative = variable<number>();
470
+ const ternary = expr({ condition, result, alternative })("condition ? result : alternative");
471
+ ```
472
+
473
+ ### 自动内联优化
474
+
475
+ 编译器自动将只被引用一次的子表达式内联到使用位置,减少中间计算:
476
+
477
+ ```typescript
478
+ const x = variable<number>();
479
+ const y = variable<number>();
480
+
481
+ const sum = expr({ x, y })("x + y");
482
+ const product = expr({ x, y })("x * y");
483
+ const result = expr({ sum, product })("sum + product");
484
+
485
+ // 自动内联后,编译结果为:
486
+ // [["x", "y"], "($0+$1)+($0*$1)"]
487
+ // 而不是 [["x", "y"], "$0+$1", "$0*$1", "$2+$3"]
488
+
489
+ const compiled = compile(result, { x, y });
490
+ const value = evaluate(compiled, { x: 2, y: 3 });
491
+ // => 11
492
+ ```
493
+
494
+ ### 直接编译对象和数组
495
+
496
+ `compile` 函数支持直接编译包含 Proxy 的对象和数组:
497
+
498
+ ```typescript
499
+ const x = variable<number>();
500
+ const y = variable<number>();
501
+ const sum = expr({ x, y })("x + y");
502
+
503
+ // 编译对象
504
+ const objCompiled = compile({ result: sum, original: { x, y } }, { x, y });
505
+ const objResult = evaluate(objCompiled, { x: 10, y: 20 });
506
+ // => { result: 30, original: { x: 10, y: 20 } }
507
+
508
+ // 编译数组
509
+ const arrCompiled = compile([x, sum, 100], { x, y });
510
+ const arrResult = evaluate(arrCompiled, { x: 5, y: 3 });
511
+ // => [5, 8, 100]
512
+ ```
513
+
278
514
  ## 序列化和传输
279
515
 
280
516
  编译后的数据可以轻松进行 JSON 序列化,适合网络传输或持久化存储:
@@ -296,6 +532,89 @@ const deserialized = JSON.parse(json);
296
532
  const value = evaluate(deserialized, { x: 5, y: 3 });
297
533
  ```
298
534
 
535
+ ## 编译数据格式
536
+
537
+ ### V1 格式(基础表达式)
538
+
539
+ 基础格式为 JSON 数组:`[variableNames, ...expressions]`
540
+
541
+ ```typescript
542
+ // 输入
543
+ const sum = expr({ x, y })("x + y");
544
+ const compiled = compile(sum, { x, y });
545
+
546
+ // 输出
547
+ // [["x", "y"], "$0+$1"]
548
+ // $0 引用 x,$1 引用 y
549
+ ```
550
+
551
+ ### V2 格式(控制流节点)
552
+
553
+ 启用短路求值时,生成包含控制流节点的格式:
554
+
555
+ ```typescript
556
+ // 输入
557
+ const result = expr({ a, b })("a || b");
558
+ const compiled = compile(result, { a, b }, { shortCircuit: true });
559
+
560
+ // 输出
561
+ // [
562
+ // ["a", "b"],
563
+ // ["br", "$0", 1], // 如果 $0 为 truthy,跳过 1 条指令
564
+ // "$1", // 否则求值 $1
565
+ // ["phi"] // 取最近求值结果
566
+ // ]
567
+ ```
568
+
569
+ **控制流节点类型:**
570
+
571
+ - `["br", condition, offset]` - 条件跳转,条件为真时跳过 offset 条指令
572
+ - `["jmp", offset]` - 无条件跳转,跳过 offset 条指令
573
+ - `["phi"]` - 取最近求值结果(用于合并分支)
574
+
575
+ ## 错误处理
576
+
577
+ ### 编译时错误
578
+
579
+ 编译器会检测并报告以下错误:
580
+
581
+ ```typescript
582
+ const x = variable<number>();
583
+ const y = variable<number>();
584
+
585
+ // 错误:引用未定义的变量
586
+ const invalid = expr({ x, y })("x + y + z");
587
+ compile(invalid, { x, y });
588
+ // => Error: Undefined variable(s): z
589
+
590
+ // 错误:变量名冲突
591
+ const xy = variable<number>();
592
+ const conflict = expr({ xy, x })("xy + x");
593
+ // 正确处理:编译器能区分 xy 和 x
594
+ const compiled = compile(conflict, { xy, x });
595
+ // => [["xy", "x"], "$0+$1"]
596
+ ```
597
+
598
+ ### 运行时错误
599
+
600
+ 求值器会验证输入并报告运行时错误:
601
+
602
+ ```typescript
603
+ const x = variable<number>();
604
+ const y = variable<number>();
605
+
606
+ const sum = expr({ x, y })("x + y");
607
+ const compiled = compile(sum, { x, y });
608
+
609
+ // 错误:缺少必需变量
610
+ evaluate(compiled, { x: 2 });
611
+ // => Error: Missing required variable: y
612
+
613
+ // 错误:无效的编译数据
614
+ evaluate([], { x: 1 });
615
+ // => Error: Invalid compiled data: must have at least variable names
616
+ ```
617
+
299
618
  ## 类型安全
300
619
 
301
620
  项目充分利用 TypeScript 的类型系统进行编译时检查和类型推导:
@@ -309,28 +628,150 @@ const y = variable<string>();
309
628
  const valid = expr({ x })("-x"); // 编译器推导为 number
310
629
  ```
311
630
 
631
+ ## 实际应用示例
632
+
633
+ ### 动态表单验证规则
634
+
635
+ ```typescript
636
+ const formData = variable<{
637
+ username: string;
638
+ password: string;
639
+ confirmPassword: string;
640
+ age: number;
641
+ }>();
642
+
643
+ // 创建验证规则表达式
644
+ const isUsernameValid = expr({ formData })("formData.username.length >= 3 && formData.username.length <= 20");
645
+
646
+ const isPasswordValid = expr({ formData })("formData.password.length >= 8 && /[A-Z]/.test(formData.password)");
647
+
648
+ const doPasswordsMatch = expr({ formData })("formData.password === formData.confirmPassword");
649
+
650
+ const isAgeValid = expr({ formData })("formData.age >= 18 && formData.age <= 120");
651
+
652
+ const isFormValid = expr({
653
+ isUsernameValid,
654
+ isPasswordValid,
655
+ doPasswordsMatch,
656
+ isAgeValid,
657
+ })("isUsernameValid && isPasswordValid && doPasswordsMatch && isAgeValid");
658
+
659
+ // 编译一次,多次执行
660
+ const compiled = compile(isFormValid, { formData });
661
+
662
+ // 在表单输入时实时验证
663
+ evaluate(compiled, {
664
+ formData: {
665
+ username: "john_doe",
666
+ password: "Secure123",
667
+ confirmPassword: "Secure123",
668
+ age: 25,
669
+ },
670
+ }); // => true
671
+ ```
672
+
673
+ ### 数据转换管道
674
+
675
+ ```typescript
676
+ const rawData = variable<any[]>();
677
+ const config = variable<{
678
+ minValue: number;
679
+ maxValue: number;
680
+ transform: (x: number) => number;
681
+ }>();
682
+
683
+ // 构建数据处理管道
684
+ const filtered = rawData.filter(
685
+ lambda<[any], boolean>((item) =>
686
+ expr({ item, config })("item.value >= config.minValue && item.value <= config.maxValue")
687
+ )
688
+ );
689
+
690
+ const transformed = filtered.map(
691
+ lambda<[any], number>((item) => expr({ item, config })("config.transform(item.value)"))
692
+ );
693
+
694
+ const sorted = transformed.toSorted(lambda<[number, number], number>((a, b) => expr({ a, b })("a - b")));
695
+
696
+ const pipeline = compile(sorted, { rawData, config });
697
+
698
+ // 执行数据处理
699
+ const result = evaluate(pipeline, {
700
+ rawData: [{ value: 10 }, { value: 5 }, { value: 20 }, { value: 15 }],
701
+ config: { minValue: 8, maxValue: 18, transform: (x: number) => x * 2 },
702
+ });
703
+ // => [10, 20, 30] (5 被过滤,10*2=20, 15*2=30, 20 被过滤)
704
+ ```
705
+
706
+ ### 规则引擎
707
+
708
+ ```typescript
709
+ // 定义规则条件
710
+ const user = variable<{
711
+ age: number;
712
+ role: string;
713
+ balance: number;
714
+ }>();
715
+
716
+ const isEligible = expr({ user })(
717
+ "(user.age >= 18 && user.age <= 65) && (user.role === 'premium' || user.balance > 10000)"
718
+ );
719
+
720
+ const discountRate = expr({ user, isEligible })("isEligible ? (user.role === 'premium' ? 0.2 : 0.1) : 0");
721
+
722
+ const rule = compile(discountRate, { user });
723
+
724
+ // 应用规则
725
+ const discount = evaluate(rule, {
726
+ user: { age: 30, role: "premium", balance: 5000 },
727
+ });
728
+ // => 0.2 (20% 折扣)
729
+ ```
730
+
312
731
  ## 性能考虑
313
732
 
314
733
  - **编译时间**:编译过程涉及依赖分析和拓扑排序,通常快速完成
315
734
  - **执行时间**:表达式通过 `new Function()` 编译为原生 JavaScript,执行性能接近原生代码
316
735
  - **内存占用**:编译数据为纯 JSON,占用空间小,适合在网络上传输
736
+ - **缓存机制**:求值器缓存已编译的函数,重复执行时性能更优
737
+
738
+ ### 最佳实践
739
+
740
+ 1. **编译一次,多次执行**:对于重复使用的表达式,先编译后多次求值
741
+
742
+ ```typescript
743
+ const compiled = compile(expression, variables);
744
+ // 缓存 compiled,多次调用 evaluate
745
+ evaluate(compiled, values1);
746
+ evaluate(compiled, values2);
747
+ ```
748
+
749
+ 2. **合理使用短路求值**:对于条件表达式,启用短路求值可以避免不必要的计算
750
+
751
+ ```typescript
752
+ compile(expression, variables, { shortCircuit: true });
753
+ ```
754
+
755
+ 3. **利用自动内联**:编译器会自动内联只引用一次的子表达式,无需手动优化
756
+
757
+ 4. **优先使用 Proxy 链式调用**:对于对象属性访问,使用 `config.timeout` 比 `expr({ config })("config.timeout")` 更简洁且类型更安全
317
758
 
318
759
  ## 项目结构
319
760
 
320
761
  ```
321
762
  src/
322
- ├── index.ts # 导出入口
323
- ├── variable.ts # variable<T>() 函数
324
- ├── expr.ts # expr() 函数
325
- ├── template.ts # t() 标签模板函数
326
- ├── compile.ts # 编译器(内联优化、短路求值)
327
- ├── evaluate.ts # 运行时求值
328
- ├── parser.ts # 表达式 AST 解析器
329
- ├── type-parser.ts # TypeScript 类型级表达式解析
330
- ├── proxy-variable.ts # Proxy 变量实现
331
- ├── proxy-metadata.ts # Proxy 元数据管理
332
- ├── types.ts # 类型定义
333
- └── *.test.ts # 测试文件
763
+ ├── index.ts # 导出入口
764
+ ├── variable.ts # variable<T>() 函数
765
+ ├── expr.ts # expr() 函数
766
+ ├── template.ts # t() 标签模板函数
767
+ ├── lambda.ts # lambda() 函数(数组方法支持)
768
+ ├── compile.ts # 编译器(内联优化、短路求值)
769
+ ├── evaluate.ts # 运行时求值
770
+ ├── parser.ts # 表达式 AST 解析器
771
+ ├── type-parser.ts # TypeScript 类型级表达式解析
772
+ ├── proxy-variable.ts # Proxy 变量实现
773
+ ├── proxy-metadata.ts # Proxy 元数据管理
774
+ └── types.ts # 类型定义(Variable、Expression、Lambda 等)
334
775
  ```
335
776
 
336
777
  ## 开发
package/dist/index.d.mts CHANGED
@@ -11,14 +11,45 @@ type ProxyExpression<T = unknown> = {
11
11
  * 参数可以是原始值或对应的 Proxy
12
12
  */
13
13
  type ProxifyArgs<T extends unknown[]> = { [K in keyof T]: T[K] | Proxify<T[K]> };
14
+ /**
15
+ * 需要特殊处理的数组方法名(有泛型参数,需要显式定义以保留类型推导)
16
+ */
17
+ type ProxifiedArrayMethods = "map" | "flatMap" | "filter" | "reduce" | "reduceRight" | "find" | "findIndex" | "findLast" | "findLastIndex" | "every" | "some" | "forEach" | "toSorted" | "sort";
18
+ /**
19
+ * 数组类型的 Proxify 版本
20
+ * 特殊处理泛型方法(map, filter 等),确保返回值类型正确
21
+ */
22
+ type ProxifiedArray<T> = {
23
+ map<U>(callbackfn: Proxify<(value: T, index: number, array: T[]) => U>): Proxify<U[]>;
24
+ flatMap<U>(callbackfn: Proxify<(value: T, index: number, array: T[]) => U | readonly U[]>): Proxify<U[]>;
25
+ filter<S extends T>(predicate: Proxify<(value: T, index: number, array: T[]) => value is S>): Proxify<S[]>;
26
+ filter(predicate: Proxify<(value: T, index: number, array: T[]) => unknown>): Proxify<T[]>;
27
+ reduce<U>(callbackfn: Proxify<(previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U>, initialValue: U | Proxify<U>): Proxify<U>;
28
+ reduce(callbackfn: Proxify<(previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T>): Proxify<T>;
29
+ reduceRight<U>(callbackfn: Proxify<(previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U>, initialValue: U | Proxify<U>): Proxify<U>;
30
+ reduceRight(callbackfn: Proxify<(previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T>): Proxify<T>;
31
+ find<S extends T>(predicate: Proxify<(value: T, index: number, obj: T[]) => value is S>): Proxify<S | undefined>;
32
+ find(predicate: Proxify<(value: T, index: number, obj: T[]) => unknown>): Proxify<T | undefined>;
33
+ findIndex(predicate: Proxify<(value: T, index: number, obj: T[]) => unknown>): Proxify<number>;
34
+ findLast<S extends T>(predicate: Proxify<(value: T, index: number, array: T[]) => value is S>): Proxify<S | undefined>;
35
+ findLast(predicate: Proxify<(value: T, index: number, array: T[]) => unknown>): Proxify<T | undefined>;
36
+ findLastIndex(predicate: Proxify<(value: T, index: number, array: T[]) => unknown>): Proxify<number>;
37
+ every<S extends T>(predicate: Proxify<(value: T, index: number, array: T[]) => value is S>): Proxify<boolean>;
38
+ every(predicate: Proxify<(value: T, index: number, array: T[]) => unknown>): Proxify<boolean>;
39
+ some(predicate: Proxify<(value: T, index: number, array: T[]) => unknown>): Proxify<boolean>;
40
+ forEach(callbackfn: Proxify<(value: T, index: number, array: T[]) => void>): Proxify<void>;
41
+ toSorted(compareFn?: Proxify<(a: T, b: T) => number>): Proxify<T[]>;
42
+ sort(compareFn?: Proxify<(a: T, b: T) => number>): Proxify<T[]>;
43
+ } & { [K in Exclude<keyof T[], ProxifiedArrayMethods>]: Proxify<T[][K]> };
14
44
  /**
15
45
  * 将类型 T 转换为 Proxy 包装类型
16
46
  * - 始终包含 ProxyExpression<T> 标记,用于 compile 函数类型检查
17
47
  * - 函数类型:保持函数签名,但参数允许 Proxy 或原始值,返回值递归应用 Proxify
48
+ * - 数组类型:使用 ProxifiedArray 特殊处理泛型方法
18
49
  * - 对象类型:映射所有属性为 Proxify
19
50
  * - 原始类型:保持不变(返回 ProxyExpression 包装)
20
51
  */
21
- type Proxify<T> = ProxyExpression<T> & (T extends ((...args: infer Args) => infer R) ? (...args: ProxifyArgs<Args>) => Proxify<R> : T extends object ? { [K in keyof T]: Proxify<T[K]> } : unknown);
52
+ type Proxify<T> = ProxyExpression<T> & (T extends ((...args: infer Args) => infer R) ? (...args: ProxifyArgs<Args>) => Proxify<R> : T extends readonly (infer E)[] ? ProxifiedArray<E> : T extends object ? { [K in keyof T]: Proxify<T[K]> } : unknown);
22
53
  /**
23
54
  * Variable 类型定义
24
55
  * 总是返回 Proxy 包装后的类型
@@ -100,6 +131,55 @@ type InferContextType<C> = { [K in keyof C]: C[K] extends Variable<infer T> ? T
100
131
  * @template E - Expression 类型
101
132
  */
102
133
  type InferExpressionType<E> = E extends Expression<unknown, infer R> ? R : never;
134
+ /**
135
+ * Lambda 参数代理类型
136
+ * 与普通 Proxify<T> 相同,但标记为 lambda 参数
137
+ */
138
+ type LambdaParam<T> = Proxify<T>;
139
+ /**
140
+ * 原始类型
141
+ */
142
+ type Primitive = string | number | boolean | null | undefined | symbol | bigint;
143
+ /**
144
+ * 深度允许 Proxy 或原始值的类型
145
+ * 用于 lambda 返回值,允许对象/数组中混合 Proxy 和原始值
146
+ */
147
+ type DeepPartialProxy<T> = T extends Primitive ? T : T extends readonly (infer E)[] ? readonly (Proxify<E> | DeepPartialProxy<E>)[] : T extends object ? { [K in keyof T]: Proxify<T[K]> | DeepPartialProxy<T[K]> } : T;
148
+ /**
149
+ * Lambda 函数体返回值类型
150
+ * 支持返回:
151
+ * - Proxify<R>: 完整的代理表达式
152
+ * - 原始值: 字符串、数字等
153
+ * - 对象/数组: 可以混合 Proxy 值和原始值
154
+ */
155
+ type LambdaBodyResult<T> = Proxify<T> | DeepPartialProxy<T>;
156
+ /**
157
+ * Lambda 构建函数签名
158
+ * @template Args - 参数类型元组
159
+ * @template R - 返回值类型
160
+ */
161
+ type LambdaBuilder<Args extends unknown[], R> = (...params: { [K in keyof Args]: LambdaParam<Args[K]> }) => LambdaBodyResult<R>;
162
+ /**
163
+ * Lambda 表达式类型
164
+ * 表示一个可序列化的函数
165
+ */
166
+ type Lambda<Args extends unknown[], R> = Proxify<(...args: Args) => R>;
167
+ /**
168
+ * 从 Lambda 类型提取参数类型
169
+ */
170
+ type InferLambdaArgs<L> = L extends Lambda<infer Args, unknown> ? Args : never;
171
+ /**
172
+ * 从 Lambda 类型提取返回类型
173
+ */
174
+ type InferLambdaReturn<L> = L extends Lambda<unknown[], infer R> ? R : never;
175
+ /**
176
+ * 常用 Lambda 类型别名
177
+ */
178
+ type MapCallback<T, R> = Lambda<[T, number, T[]], R>;
179
+ type FilterCallback<T> = Lambda<[T, number, T[]], boolean>;
180
+ type ReduceCallback<T, R> = Lambda<[R, T, number, T[]], R>;
181
+ type FindCallback<T> = Lambda<[T, number, T[]], boolean>;
182
+ type SortCallback<T> = Lambda<[T, T], number>;
103
183
  //#endregion
104
184
  //#region src/compile.d.ts
105
185
  /**
@@ -117,7 +197,7 @@ interface CompileOptions {
117
197
  * 将 Proxy Expression 编译为可序列化的 JSON 结构
118
198
  *
119
199
  * @template TResult - 表达式结果类型
120
- * @param expression - Proxy Expression
200
+ * @param expression - Proxy Expression,或包含 Proxy 的对象/数组/原始值
121
201
  * @param variables - 所有使用的变量定义
122
202
  * @param options - 编译选项
123
203
  * @returns 编译后的数据结构 [变量名列表, 表达式1, 表达式2, ...]
@@ -134,7 +214,7 @@ interface CompileOptions {
134
214
  * // => [["x", "y"], "($0+$1)*$0"]
135
215
  * ```
136
216
  */
137
- declare function compile<TResult>(expression: ProxyExpression<TResult>, variables: Record<string, unknown>, options?: CompileOptions): CompiledData;
217
+ declare function compile<TResult>(expression: LambdaBodyResult<TResult>, variables: Record<string, unknown>, options?: CompileOptions): CompiledData;
138
218
  //#endregion
139
219
  //#region src/evaluate.d.ts
140
220
  /**
@@ -359,6 +439,27 @@ type ExpressionType<Source extends string, TContext> = ValidateExpression<Source
359
439
  */
360
440
  declare function expr<TContext extends Record<string, unknown>>(context: TContext): <TSource extends string>(source: ValidateExpression<TSource, TContext> extends never ? never : TSource) => Proxify<InferExpressionResult<TSource, TContext>>;
361
441
  //#endregion
442
+ //#region src/lambda.d.ts
443
+ /**
444
+ * 创建类型安全的 lambda 表达式
445
+ *
446
+ * @template Args - 参数类型元组
447
+ * @template R - 返回值类型
448
+ * @param builder - Lambda 构建函数,接收参数代理,返回函数体表达式
449
+ * @returns Lambda 表达式代理
450
+ *
451
+ * @example
452
+ * ```ts
453
+ * const add = lambda<[number, number], number>(
454
+ * (a, b) => expr({ a, b })("a + b")
455
+ * );
456
+ *
457
+ * const numbers = variable<number[]>();
458
+ * const sum = numbers.reduce(add, 0);
459
+ * ```
460
+ */
461
+ declare function lambda<Args extends unknown[], R>(builder: LambdaBuilder<Args, R>): Lambda<Args, R>;
462
+ //#endregion
362
463
  //#region src/proxy-metadata.d.ts
363
464
  /**
364
465
  * 检查对象是否是 Proxy variable
@@ -409,5 +510,5 @@ declare function variable<T>(): Variable<T>;
409
510
  */
410
511
  declare function getVariableId(variable: unknown): symbol | undefined;
411
512
  //#endregion
412
- export { type BranchNode, type CompileContext, type CompileOptions, type CompiledData, type CompiledExpression, type ContextTypeMap, type ControlFlowNode, type ExprNode, type Expression, type ExpressionType, type ExtractType, type InferContextType, type InferExpressionResult, type InferExpressionType, type InferVariableType, type JumpNode, type ParseExpression, type PhiNode, type Proxify, type ProxyExpression, type ValidateExpression, type Variable, compile, evaluate, expr, getVariableId, isProxy, isProxyExpression, isProxyVariable, t, variable };
513
+ export { type BranchNode, type CompileContext, type CompileOptions, type CompiledData, type CompiledExpression, type ContextTypeMap, type ControlFlowNode, type ExprNode, type Expression, type ExpressionType, type ExtractType, type FilterCallback, type FindCallback, type InferContextType, type InferExpressionResult, type InferExpressionType, type InferLambdaArgs, type InferLambdaReturn, type InferVariableType, type JumpNode, type Lambda, type LambdaBuilder, type LambdaParam, type MapCallback, type ParseExpression, type PhiNode, type Proxify, type ProxyExpression, type ReduceCallback, type SortCallback, type ValidateExpression, type Variable, compile, evaluate, expr, getVariableId, isProxy, isProxyExpression, isProxyVariable, lambda, t, variable };
413
514
  //# sourceMappingURL=index.d.mts.map