@codehz/json-expr 0.4.0 → 0.5.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/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, wrap } from "@codehz/json-expr";
29
32
 
30
33
  // 定义类型化变量(使用 TypeScript 泛型)
31
34
  const x = variable<number>();
@@ -43,6 +46,19 @@ 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")));
57
+
58
+ // 使用 wrap 包装静态值
59
+ const pattern = wrap(/^[a-z]+$/i);
60
+ const input = variable<string>();
61
+ const isValid = pattern.test(input);
46
62
  ```
47
63
 
48
64
  ## 核心概念
@@ -215,8 +231,270 @@ const result = evaluate(compiled, { name: "Alice" });
215
231
  // => "Hello, Alice!"
216
232
  ```
217
233
 
234
+ ### `lambda<Args, R>(builder: LambdaBuilder<Args, R>): Lambda<Args, R>`
235
+
236
+ 创建类型安全的 lambda 表达式,用于数组方法(map、filter、reduce 等)。
237
+
238
+ **参数:**
239
+
240
+ - `builder` - Lambda 构建函数,接收参数代理,返回函数体表达式
241
+
242
+ **返回值:** Lambda 表达式,可在数组方法中使用
243
+
244
+ **示例:**
245
+
246
+ ```typescript
247
+ import { lambda } from "@codehz/json-expr";
248
+
249
+ // 单参数 lambda
250
+ const numbers = variable<number[]>();
251
+ const doubled = numbers.map(lambda<[number], number>((n) => expr({ n })("n * 2")));
252
+
253
+ const compiled = compile(doubled, { numbers });
254
+ const result = evaluate(compiled, { numbers: [1, 2, 3] });
255
+ // => [2, 4, 6]
256
+
257
+ // 多参数 lambda(reduce)
258
+ const sum = numbers.reduce(
259
+ lambda<[number, number], number>((acc, val) => expr({ acc, val })("acc + val")),
260
+ 0
261
+ );
262
+
263
+ // 捕获外部变量
264
+ const multiplier = variable<number>();
265
+ const scaled = numbers.map(lambda<[number], number>((n) => expr({ n, multiplier })("n * multiplier")));
266
+ ```
267
+
268
+ ### `wrap<T>(value: T): Proxify<T>`
269
+
270
+ 将静态值包装为 Proxy Expression,使其可以像 Variable 一样调用方法和访问属性。
271
+
272
+ **参数:**
273
+
274
+ - `value` - 要包装的静态值(支持原始值、对象、数组、Date、RegExp、BigInt、URL、Map、Set、TypedArray 等)
275
+
276
+ **返回值:** Proxy Expression,可以继续链式调用
277
+
278
+ **示例:**
279
+
280
+ ```typescript
281
+ // 包装 RegExp
282
+ const pattern = wrap(/^[a-z]+$/i);
283
+ const input = variable<string>();
284
+ const isValid = pattern.test(input);
285
+
286
+ const compiled = compile(isValid, { input });
287
+ evaluate(compiled, { input: "hello" }); // => true
288
+ evaluate(compiled, { input: "hello123" }); // => false
289
+
290
+ // 包装 Date
291
+ const now = wrap(new Date("2024-01-01"));
292
+ const year = now.getFullYear();
293
+
294
+ // 包装数组
295
+ const staticNumbers = wrap([1, 2, 3, 4, 5]);
296
+ const x = variable<number>();
297
+ const doubled = staticNumbers.map(lambda((n: number) => expr({ n, x })("n * x")));
298
+
299
+ // 包装对象
300
+ const config = wrap({ port: 8080, host: "localhost" });
301
+ const port = config.port; // 直接访问属性
302
+
303
+ // 包装 Map
304
+ const map = wrap(
305
+ new Map([
306
+ ["a", 1],
307
+ ["b", 2],
308
+ ])
309
+ );
310
+ const key = variable<string>();
311
+ const value = map.get(key);
312
+
313
+ // 链式调用
314
+ const text = wrap(" hello world ");
315
+ const result = text.trim().toUpperCase().replace("HELLO", "HI");
316
+ // => "HI WORLD"
317
+ ```
318
+
218
319
  ## 高级用法
219
320
 
321
+ ### 包装静态值(wrap)
322
+
323
+ `wrap()` 函数可以将任意静态值转换为 Proxy Expression,使其可以像 Variable 一样调用方法和访问属性。这在需要对常量值执行操作时非常有用。
324
+
325
+ **基本用法:**
326
+
327
+ ```typescript
328
+ // 不使用 wrap(传统方式)
329
+ interface Validator {
330
+ match(text: string, pattern: RegExp): boolean;
331
+ }
332
+ const validator = variable<Validator>();
333
+ const result = validator.match("hello", /^[a-z]+$/i);
334
+
335
+ // 使用 wrap(推荐方式)
336
+ const pattern = wrap(/^[a-z]+$/i);
337
+ const input = variable<string>();
338
+ const result = pattern.test(input);
339
+ ```
340
+
341
+ **支持的类型:**
342
+
343
+ ```typescript
344
+ // 原始值
345
+ const num = wrap(42);
346
+ const str = wrap("hello");
347
+ const bool = wrap(true);
348
+
349
+ // Date 和 RegExp
350
+ const date = wrap(new Date("2024-01-01"));
351
+ const year = date.getFullYear();
352
+
353
+ const regex = wrap(/\d+/g);
354
+ const text = variable<string>();
355
+ const matches = text.match(regex);
356
+
357
+ // BigInt
358
+ const bigNum = wrap(123456789n);
359
+ const x = variable<bigint>();
360
+ const sum = expr({ bigNum, x })("bigNum + x");
361
+
362
+ // URL
363
+ const url = wrap(new URL("https://example.com/path"));
364
+ const host = url.hostname;
365
+ const port = url.port;
366
+
367
+ // Map 和 Set
368
+ const map = wrap(
369
+ new Map([
370
+ ["key1", 100],
371
+ ["key2", 200],
372
+ ])
373
+ );
374
+ const key = variable<string>();
375
+ const value = map.get(key);
376
+
377
+ const set = wrap(new Set([1, 2, 3]));
378
+ const num = variable<number>();
379
+ const has = set.has(num);
380
+
381
+ // TypedArray
382
+ const arr = wrap(new Uint8Array([10, 20, 30]));
383
+ const index = variable<number>();
384
+ const value = expr({ arr, index })("arr[index]");
385
+
386
+ // 数组和对象
387
+ const numbers = wrap([1, 2, 3, 4, 5]);
388
+ const multiplier = variable<number>();
389
+ const scaled = numbers.map(lambda((n: number) => expr({ n, multiplier })("n * multiplier")));
390
+
391
+ const config = wrap({ port: 8080, host: "localhost" });
392
+ const port = config.port;
393
+ ```
394
+
395
+ **链式调用:**
396
+
397
+ ```typescript
398
+ const text = wrap(" Hello, World! ");
399
+ const result = text.trim().toLowerCase().replace("world", "universe");
400
+ // => "hello, universe!"
401
+ ```
402
+
403
+ **与 variable 结合:**
404
+
405
+ ```typescript
406
+ const staticData = wrap({ users: ["alice", "bob", "charlie"] });
407
+ const index = variable<number>();
408
+ const username = expr({ staticData, index })("staticData.users[index]");
409
+
410
+ const compiled = compile(username, { index });
411
+ evaluate(compiled, { index: 1 }); // => "bob"
412
+ ```
413
+
414
+ ### Proxy 变量系统
415
+
416
+ `variable()` 创建的变量是 Proxy 对象,支持链式属性访问和方法调用,所有操作都会自动转换为表达式。
417
+
418
+ **属性访问:**
419
+
420
+ ```typescript
421
+ const config = variable<{
422
+ timeout: number;
423
+ retries: number;
424
+ database: {
425
+ host: string;
426
+ port: number;
427
+ };
428
+ }>();
429
+
430
+ // 链式属性访问
431
+ const timeout = config.timeout; // 自动转换为表达式
432
+ const dbHost = config.database.host; // 支持嵌套访问
433
+
434
+ const compiled = compile(timeout, { config });
435
+ const result = evaluate(compiled, {
436
+ config: { timeout: 5000, retries: 3, database: { host: "localhost", port: 5432 } },
437
+ });
438
+ // => 5000
439
+ ```
440
+
441
+ **方法调用:**
442
+
443
+ ```typescript
444
+ const calculator = variable<{
445
+ add(a: number, b: number): number;
446
+ multiply(x: number, y: number): number;
447
+ }>();
448
+
449
+ // 方法调用
450
+ const sum = calculator.add(1, 2);
451
+ const product = calculator.multiply(5, 3);
452
+
453
+ // 链式方法调用
454
+ const builder = variable<{
455
+ setName(name: string): typeof builder;
456
+ build(): { name: string };
457
+ }>();
458
+ const result = builder.setName("test").build();
459
+
460
+ // 编译并执行
461
+ const compiled = compile(sum, { calculator });
462
+ const value = evaluate(compiled, {
463
+ calculator: {
464
+ add: (a, b) => a + b,
465
+ multiply: (x, y) => x * y,
466
+ },
467
+ });
468
+ // => 3
469
+ ```
470
+
471
+ **数组方法:**
472
+
473
+ 数组变量支持所有标准数组方法,并自动处理类型推导:
474
+
475
+ ```typescript
476
+ const numbers = variable<number[]>();
477
+ const users = variable<{ id: number; name: string }[]>();
478
+
479
+ // map
480
+ const doubled = numbers.map((n) => expr({ n })("n * 2"));
481
+
482
+ // filter
483
+ const activeUsers = users.filter((u) => expr({ u })("u.active"));
484
+
485
+ // reduce
486
+ const sum = numbers.reduce(
487
+ lambda<[number, number], number>((acc, val) => expr({ acc, val })("acc + val")),
488
+ 0
489
+ );
490
+
491
+ // find, some, every, sort 等
492
+ const firstMatch = users.find((u) => expr({ u })("u.id === 1"));
493
+ const hasAdmins = users.some((u) => expr({ u })("u.role === 'admin'"));
494
+ const allActive = users.every((u) => expr({ u })("u.active"));
495
+ const sorted = numbers.toSorted(lambda<[number, number], number>((a, b) => expr({ a, b })("a - b")));
496
+ ```
497
+
220
498
  ### 内置全局对象
221
499
 
222
500
  表达式中可以直接使用以下内置对象(无需在上下文中定义):
@@ -235,6 +513,44 @@ const result = evaluate(compiled, { x: 16 });
235
513
  // => 4
236
514
  ```
237
515
 
516
+ ### 支持的运算符和语法
517
+
518
+ **算术运算符:**
519
+
520
+ - `+`, `-`, `*`, `/`, `%`, `**` (幂运算)
521
+
522
+ **比较运算符:**
523
+
524
+ - `==`, `===`, `!=`, `!==`, `<`, `>`, `<=`, `>=`
525
+
526
+ **逻辑运算符:**
527
+
528
+ - `&&`, `||`, `!`, `??` (空值合并)
529
+
530
+ **位运算符:**
531
+
532
+ - `&`, `|`, `^`, `~`, `<<`, `>>`, `>>>`
533
+
534
+ **其他运算符:**
535
+
536
+ - `? :` (三元表达式)
537
+ - `in` (属性存在检查)
538
+ - `instanceof` (类型检查)
539
+ - `typeof` (类型检测)
540
+ - `?.` (可选链)
541
+ - `?.()` (可选调用)
542
+ - `?.[]` (可选元素访问)
543
+
544
+ **语法特性:**
545
+
546
+ - 对象字面量:`{ key: value, ... }`
547
+ - 数组字面量:`[element1, element2, ...]`
548
+ - 箭头函数:`(param) => expression`
549
+ - 函数调用:`func(arg1, arg2, ...)`
550
+ - 成员访问:`obj.prop`, `obj["prop"]`, `arr[0]`
551
+ - 模板字面量(通过 `t` 标签函数)
552
+ - 分组括号:`(expression)`
553
+
238
554
  ### 条件表达式
239
555
 
240
556
  ```typescript
@@ -275,6 +591,75 @@ const result = evaluate(compiled, { a: 2, b: 3 });
275
591
  // => (2+3) * (2*3) - (2-3) = 5 * 6 - (-1) = 30 + 1 = 31
276
592
  ```
277
593
 
594
+ ### 短路求值(控制流优化)
595
+
596
+ 编译器支持为 `&&`、`||`、`??` 和三元表达式生成短路求值代码,避免不必要的计算:
597
+
598
+ ```typescript
599
+ const a = variable<boolean>();
600
+ const b = variable<boolean>();
601
+
602
+ // 逻辑或短路
603
+ const orExpr = expr({ a, b })("a || b");
604
+ const compiled = compile(orExpr, { a, b }, { shortCircuit: true });
605
+
606
+ // 当 a 为 true 时,b 不会被求值
607
+ // 编译数据包含控制流节点:
608
+ // [["a", "b"], ["br", "$0", 1], "$1", ["phi"]]
609
+
610
+ // 空值合并
611
+ const x = variable<number | null>();
612
+ const y = variable<number>();
613
+ const coalesce = expr({ x, y })("x ?? y");
614
+
615
+ // 三元表达式
616
+ const condition = variable<boolean>();
617
+ const result = variable<number>();
618
+ const alternative = variable<number>();
619
+ const ternary = expr({ condition, result, alternative })("condition ? result : alternative");
620
+ ```
621
+
622
+ ### 自动内联优化
623
+
624
+ 编译器自动将只被引用一次的子表达式内联到使用位置,减少中间计算:
625
+
626
+ ```typescript
627
+ const x = variable<number>();
628
+ const y = variable<number>();
629
+
630
+ const sum = expr({ x, y })("x + y");
631
+ const product = expr({ x, y })("x * y");
632
+ const result = expr({ sum, product })("sum + product");
633
+
634
+ // 自动内联后,编译结果为:
635
+ // [["x", "y"], "($0+$1)+($0*$1)"]
636
+ // 而不是 [["x", "y"], "$0+$1", "$0*$1", "$2+$3"]
637
+
638
+ const compiled = compile(result, { x, y });
639
+ const value = evaluate(compiled, { x: 2, y: 3 });
640
+ // => 11
641
+ ```
642
+
643
+ ### 直接编译对象和数组
644
+
645
+ `compile` 函数支持直接编译包含 Proxy 的对象和数组:
646
+
647
+ ```typescript
648
+ const x = variable<number>();
649
+ const y = variable<number>();
650
+ const sum = expr({ x, y })("x + y");
651
+
652
+ // 编译对象
653
+ const objCompiled = compile({ result: sum, original: { x, y } }, { x, y });
654
+ const objResult = evaluate(objCompiled, { x: 10, y: 20 });
655
+ // => { result: 30, original: { x: 10, y: 20 } }
656
+
657
+ // 编译数组
658
+ const arrCompiled = compile([x, sum, 100], { x, y });
659
+ const arrResult = evaluate(arrCompiled, { x: 5, y: 3 });
660
+ // => [5, 8, 100]
661
+ ```
662
+
278
663
  ## 序列化和传输
279
664
 
280
665
  编译后的数据可以轻松进行 JSON 序列化,适合网络传输或持久化存储:
@@ -296,6 +681,89 @@ const deserialized = JSON.parse(json);
296
681
  const value = evaluate(deserialized, { x: 5, y: 3 });
297
682
  ```
298
683
 
684
+ ## 编译数据格式
685
+
686
+ ### V1 格式(基础表达式)
687
+
688
+ 基础格式为 JSON 数组:`[variableNames, ...expressions]`
689
+
690
+ ```typescript
691
+ // 输入
692
+ const sum = expr({ x, y })("x + y");
693
+ const compiled = compile(sum, { x, y });
694
+
695
+ // 输出
696
+ // [["x", "y"], "$0+$1"]
697
+ // $0 引用 x,$1 引用 y
698
+ ```
699
+
700
+ ### V2 格式(控制流节点)
701
+
702
+ 启用短路求值时,生成包含控制流节点的格式:
703
+
704
+ ```typescript
705
+ // 输入
706
+ const result = expr({ a, b })("a || b");
707
+ const compiled = compile(result, { a, b }, { shortCircuit: true });
708
+
709
+ // 输出
710
+ // [
711
+ // ["a", "b"],
712
+ // ["br", "$0", 1], // 如果 $0 为 truthy,跳过 1 条指令
713
+ // "$1", // 否则求值 $1
714
+ // ["phi"] // 取最近求值结果
715
+ // ]
716
+ ```
717
+
718
+ **控制流节点类型:**
719
+
720
+ - `["br", condition, offset]` - 条件跳转,条件为真时跳过 offset 条指令
721
+ - `["jmp", offset]` - 无条件跳转,跳过 offset 条指令
722
+ - `["phi"]` - 取最近求值结果(用于合并分支)
723
+
724
+ ## 错误处理
725
+
726
+ ### 编译时错误
727
+
728
+ 编译器会检测并报告以下错误:
729
+
730
+ ```typescript
731
+ const x = variable<number>();
732
+ const y = variable<number>();
733
+
734
+ // 错误:引用未定义的变量
735
+ const invalid = expr({ x, y })("x + y + z");
736
+ compile(invalid, { x, y });
737
+ // => Error: Undefined variable(s): z
738
+
739
+ // 错误:变量名冲突
740
+ const xy = variable<number>();
741
+ const conflict = expr({ xy, x })("xy + x");
742
+ // 正确处理:编译器能区分 xy 和 x
743
+ const compiled = compile(conflict, { xy, x });
744
+ // => [["xy", "x"], "$0+$1"]
745
+ ```
746
+
747
+ ### 运行时错误
748
+
749
+ 求值器会验证输入并报告运行时错误:
750
+
751
+ ```typescript
752
+ const x = variable<number>();
753
+ const y = variable<number>();
754
+
755
+ const sum = expr({ x, y })("x + y");
756
+ const compiled = compile(sum, { x, y });
757
+
758
+ // 错误:缺少必需变量
759
+ evaluate(compiled, { x: 2 });
760
+ // => Error: Missing required variable: y
761
+
762
+ // 错误:无效的编译数据
763
+ evaluate([], { x: 1 });
764
+ // => Error: Invalid compiled data: must have at least variable names
765
+ ```
766
+
299
767
  ## 类型安全
300
768
 
301
769
  项目充分利用 TypeScript 的类型系统进行编译时检查和类型推导:
@@ -309,28 +777,150 @@ const y = variable<string>();
309
777
  const valid = expr({ x })("-x"); // 编译器推导为 number
310
778
  ```
311
779
 
780
+ ## 实际应用示例
781
+
782
+ ### 动态表单验证规则
783
+
784
+ ```typescript
785
+ const formData = variable<{
786
+ username: string;
787
+ password: string;
788
+ confirmPassword: string;
789
+ age: number;
790
+ }>();
791
+
792
+ // 创建验证规则表达式
793
+ const isUsernameValid = expr({ formData })("formData.username.length >= 3 && formData.username.length <= 20");
794
+
795
+ const isPasswordValid = expr({ formData })("formData.password.length >= 8 && /[A-Z]/.test(formData.password)");
796
+
797
+ const doPasswordsMatch = expr({ formData })("formData.password === formData.confirmPassword");
798
+
799
+ const isAgeValid = expr({ formData })("formData.age >= 18 && formData.age <= 120");
800
+
801
+ const isFormValid = expr({
802
+ isUsernameValid,
803
+ isPasswordValid,
804
+ doPasswordsMatch,
805
+ isAgeValid,
806
+ })("isUsernameValid && isPasswordValid && doPasswordsMatch && isAgeValid");
807
+
808
+ // 编译一次,多次执行
809
+ const compiled = compile(isFormValid, { formData });
810
+
811
+ // 在表单输入时实时验证
812
+ evaluate(compiled, {
813
+ formData: {
814
+ username: "john_doe",
815
+ password: "Secure123",
816
+ confirmPassword: "Secure123",
817
+ age: 25,
818
+ },
819
+ }); // => true
820
+ ```
821
+
822
+ ### 数据转换管道
823
+
824
+ ```typescript
825
+ const rawData = variable<any[]>();
826
+ const config = variable<{
827
+ minValue: number;
828
+ maxValue: number;
829
+ transform: (x: number) => number;
830
+ }>();
831
+
832
+ // 构建数据处理管道
833
+ const filtered = rawData.filter(
834
+ lambda<[any], boolean>((item) =>
835
+ expr({ item, config })("item.value >= config.minValue && item.value <= config.maxValue")
836
+ )
837
+ );
838
+
839
+ const transformed = filtered.map(
840
+ lambda<[any], number>((item) => expr({ item, config })("config.transform(item.value)"))
841
+ );
842
+
843
+ const sorted = transformed.toSorted(lambda<[number, number], number>((a, b) => expr({ a, b })("a - b")));
844
+
845
+ const pipeline = compile(sorted, { rawData, config });
846
+
847
+ // 执行数据处理
848
+ const result = evaluate(pipeline, {
849
+ rawData: [{ value: 10 }, { value: 5 }, { value: 20 }, { value: 15 }],
850
+ config: { minValue: 8, maxValue: 18, transform: (x: number) => x * 2 },
851
+ });
852
+ // => [10, 20, 30] (5 被过滤,10*2=20, 15*2=30, 20 被过滤)
853
+ ```
854
+
855
+ ### 规则引擎
856
+
857
+ ```typescript
858
+ // 定义规则条件
859
+ const user = variable<{
860
+ age: number;
861
+ role: string;
862
+ balance: number;
863
+ }>();
864
+
865
+ const isEligible = expr({ user })(
866
+ "(user.age >= 18 && user.age <= 65) && (user.role === 'premium' || user.balance > 10000)"
867
+ );
868
+
869
+ const discountRate = expr({ user, isEligible })("isEligible ? (user.role === 'premium' ? 0.2 : 0.1) : 0");
870
+
871
+ const rule = compile(discountRate, { user });
872
+
873
+ // 应用规则
874
+ const discount = evaluate(rule, {
875
+ user: { age: 30, role: "premium", balance: 5000 },
876
+ });
877
+ // => 0.2 (20% 折扣)
878
+ ```
879
+
312
880
  ## 性能考虑
313
881
 
314
882
  - **编译时间**:编译过程涉及依赖分析和拓扑排序,通常快速完成
315
883
  - **执行时间**:表达式通过 `new Function()` 编译为原生 JavaScript,执行性能接近原生代码
316
884
  - **内存占用**:编译数据为纯 JSON,占用空间小,适合在网络上传输
885
+ - **缓存机制**:求值器缓存已编译的函数,重复执行时性能更优
886
+
887
+ ### 最佳实践
888
+
889
+ 1. **编译一次,多次执行**:对于重复使用的表达式,先编译后多次求值
890
+
891
+ ```typescript
892
+ const compiled = compile(expression, variables);
893
+ // 缓存 compiled,多次调用 evaluate
894
+ evaluate(compiled, values1);
895
+ evaluate(compiled, values2);
896
+ ```
897
+
898
+ 2. **合理使用短路求值**:对于条件表达式,启用短路求值可以避免不必要的计算
899
+
900
+ ```typescript
901
+ compile(expression, variables, { shortCircuit: true });
902
+ ```
903
+
904
+ 3. **利用自动内联**:编译器会自动内联只引用一次的子表达式,无需手动优化
905
+
906
+ 4. **优先使用 Proxy 链式调用**:对于对象属性访问,使用 `config.timeout` 比 `expr({ config })("config.timeout")` 更简洁且类型更安全
317
907
 
318
908
  ## 项目结构
319
909
 
320
910
  ```
321
911
  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 # 测试文件
912
+ ├── index.ts # 导出入口
913
+ ├── variable.ts # variable<T>() 函数
914
+ ├── expr.ts # expr() 函数
915
+ ├── template.ts # t() 标签模板函数
916
+ ├── lambda.ts # lambda() 函数(数组方法支持)
917
+ ├── compile.ts # 编译器(内联优化、短路求值)
918
+ ├── evaluate.ts # 运行时求值
919
+ ├── parser.ts # 表达式 AST 解析器
920
+ ├── type-parser.ts # TypeScript 类型级表达式解析
921
+ ├── proxy-variable.ts # Proxy 变量实现
922
+ ├── proxy-metadata.ts # Proxy 元数据管理
923
+ └── types.ts # 类型定义(Variable、Expression、Lambda 等)
334
924
  ```
335
925
 
336
926
  ## 开发