@effect-app/infra 2.16.6 → 2.16.8

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.
Files changed (43) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/_cjs/Model/filter/types/path/eager.cjs +31 -0
  3. package/_cjs/Model/filter/types/path/eager.cjs.map +1 -1
  4. package/_cjs/Model/query/dsl.cjs.map +1 -1
  5. package/_cjs/api/routing copy.cjs +196 -0
  6. package/_cjs/api/routing copy.cjs.map +1 -0
  7. package/_cjs/api/routing.cjs +2 -1
  8. package/_cjs/api/routing.cjs.map +1 -1
  9. package/dist/Model/Repository/ext.d.ts +3 -3
  10. package/dist/Model/Repository/service.d.ts +28 -14
  11. package/dist/Model/Repository/service.d.ts.map +1 -1
  12. package/dist/Model/filter/types/path/eager.d.ts +26 -29
  13. package/dist/Model/filter/types/path/eager.d.ts.map +1 -1
  14. package/dist/Model/filter/types/path/eager.js +30 -2
  15. package/dist/Model/filter/types/path/index.d.ts +1 -1
  16. package/dist/Model/filter/types/path/index.d.ts.map +1 -1
  17. package/dist/Model/filter/types/utils.d.ts +11 -0
  18. package/dist/Model/filter/types/utils.d.ts.map +1 -1
  19. package/dist/Model/query/dsl.d.ts +23 -16
  20. package/dist/Model/query/dsl.d.ts.map +1 -1
  21. package/dist/Model/query/dsl.js +1 -1
  22. package/dist/Model/query/new-kid-interpreter.d.ts +1 -1
  23. package/dist/QueueMaker/sbqueue.d.ts +2 -2
  24. package/dist/Store/service.d.ts +1 -1
  25. package/dist/api/routing copy.d.ts +160 -0
  26. package/dist/api/routing copy.d.ts.map +1 -0
  27. package/dist/api/routing copy.js +210 -0
  28. package/dist/api/routing.d.ts +12 -2
  29. package/dist/api/routing.d.ts.map +1 -1
  30. package/dist/api/routing.js +4 -3
  31. package/examples/query.ts +35 -3
  32. package/package.json +1 -1
  33. package/src/Model/Repository/service.ts +33 -13
  34. package/src/Model/filter/types/path/eager.ts +182 -50
  35. package/src/Model/filter/types/path/index.ts +1 -11
  36. package/src/Model/filter/types/utils.ts +22 -0
  37. package/src/Model/query/dsl.ts +314 -30
  38. package/src/api/routing.ts +159 -77
  39. package/test/controller.test.ts +151 -0
  40. package/test/dist/controller.test copy.js +129 -0
  41. package/test/dist/controller.test.d.ts.map +1 -0
  42. package/test/dist/controller5.test.d.ts.map +1 -0
  43. package/test/query.test.ts +385 -36
package/examples/query.ts CHANGED
@@ -1,7 +1,8 @@
1
- import { Effect, Layer, ManagedRuntime, S } from "effect-app"
1
+ import { Effect, Layer, ManagedRuntime, S, Schema } from "effect-app"
2
2
  import { makeRepo } from "../src/Model.js"
3
- import { and, one, or, order, page, project, where } from "../src/Model/query.js"
3
+ import { and, make, one, or, order, page, project, QueryWhere, where } from "../src/Model/query.js"
4
4
  import { MemoryStoreLive } from "../src/Store/Memory.js"
5
+ import { expectTypeOf } from "@effect/vitest"
5
6
 
6
7
  const str = S.Struct({ _tag: S.Literal("string"), value: S.String })
7
8
  const num = S.Struct({ _tag: S.Literal("number"), value: S.Number })
@@ -51,7 +52,8 @@ const items = [
51
52
  class SomethingRepo extends Effect.Service<SomethingRepo>()("SomethingRepo", {
52
53
  effect: Effect.gen(function*() {
53
54
  return yield* makeRepo("Union", Union, {})
54
- })
55
+ }),
56
+ dependencies: [MemoryStoreLive]
55
57
  }) {
56
58
  static readonly Test = Layer
57
59
  .effect(
@@ -96,3 +98,33 @@ const program = Effect.gen(function*() {
96
98
 
97
99
  const rt = ManagedRuntime.make(SomethingRepo.Test)
98
100
  rt.runFork(program)
101
+
102
+ const test1 = make<Union.Encoded>().pipe(
103
+ where("union._tag", "string"),
104
+ )
105
+
106
+ expectTypeOf(test1).toEqualTypeOf<QueryWhere<Union.Encoded, {
107
+ readonly _tag: "Something";
108
+ readonly id: string;
109
+ readonly displayName: string;
110
+ readonly n: string;
111
+ readonly union: {
112
+ readonly _tag: "string";
113
+ readonly value: string;
114
+ };
115
+ }>>()
116
+
117
+ const testneq1 = make<Union.Encoded>().pipe(
118
+ where("union._tag", "neq", "string"),
119
+ )
120
+
121
+ expectTypeOf(testneq1).toEqualTypeOf<QueryWhere<Union.Encoded, {
122
+ readonly _tag: "Something";
123
+ readonly id: string;
124
+ readonly displayName: string;
125
+ readonly n: string;
126
+ readonly union: {
127
+ readonly _tag: "number";
128
+ readonly value: number;
129
+ };
130
+ }>>()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-app/infra",
3
- "version": "2.16.6",
3
+ "version": "2.16.8",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -2,7 +2,7 @@
2
2
  import type { Effect, Option, PubSub, S } from "effect-app"
3
3
  import type { InvalidStateError, NotFoundError, OptimisticConcurrencyException } from "effect-app/client"
4
4
  import type { NonNegativeInt } from "effect-app/Schema/numbers"
5
- import type { FieldValues } from "../filter/types.js"
5
+ import type { FieldValues, ResolveFirstLevel } from "../filter/types.js"
6
6
  import type { QAll, Query, QueryProjection } from "../query.js"
7
7
  import type { Mapped } from "./legacy.js"
8
8
 
@@ -42,7 +42,7 @@ export interface Repository<
42
42
  >(
43
43
  q: (
44
44
  initial: Query<Encoded>
45
- ) => QueryProjection<Encoded extends From ? From : never, A, R, TType>
45
+ ) => QueryProjection<From extends Encoded ? From : never, A, R, TType>
46
46
  ): Effect.Effect<
47
47
  TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
48
48
  | (TType extends "many" ? never : NotFoundError<ItemType>)
@@ -61,7 +61,7 @@ export interface Repository<
61
61
  ) => $A,
62
62
  q2: (
63
63
  _: $A
64
- ) => QueryProjection<Encoded extends From ? From : never, A, R, TType>
64
+ ) => QueryProjection<From extends Encoded ? From : never, A, R, TType>
65
65
  ): Effect.Effect<
66
66
  TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
67
67
  | (TType extends "many" ? never : NotFoundError<ItemType>)
@@ -82,7 +82,7 @@ export interface Repository<
82
82
  q2: (_: $A) => $B,
83
83
  q3: (
84
84
  _: $B
85
- ) => QueryProjection<Encoded extends From ? From : never, A, R, TType>
85
+ ) => QueryProjection<From extends Encoded ? From : never, A, R, TType>
86
86
  ): Effect.Effect<
87
87
  TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
88
88
  | (TType extends "many" ? never : NotFoundError<ItemType>)
@@ -105,7 +105,7 @@ export interface Repository<
105
105
  q3: (_: $B) => $C,
106
106
  q4: (
107
107
  _: $C
108
- ) => QueryProjection<Encoded extends From ? From : never, A, R, TType>
108
+ ) => QueryProjection<From extends Encoded ? From : never, A, R, TType>
109
109
  ): Effect.Effect<
110
110
  TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
111
111
  | (TType extends "many" ? never : NotFoundError<ItemType>)
@@ -130,7 +130,7 @@ export interface Repository<
130
130
  q4: (_: $C) => $D,
131
131
  q5: (
132
132
  _: $D
133
- ) => QueryProjection<Encoded extends From ? From : never, A, R, TType>
133
+ ) => QueryProjection<From extends Encoded ? From : never, A, R, TType>
134
134
  ): Effect.Effect<
135
135
  TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
136
136
  | (TType extends "many" ? never : NotFoundError<ItemType>)
@@ -155,7 +155,7 @@ export interface Repository<
155
155
  q3: (_: $B) => $C,
156
156
  q4: (_: $C) => $D,
157
157
  q5: (_: $D) => $E,
158
- q6: (_: $E) => QueryProjection<Encoded extends From ? From : never, A, R, TType>
158
+ q6: (_: $E) => QueryProjection<From extends Encoded ? From : never, A, R, TType>
159
159
  ): Effect.Effect<
160
160
  TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
161
161
  | (TType extends "many" ? never : NotFoundError<ItemType>)
@@ -182,7 +182,7 @@ export interface Repository<
182
182
  q4: (_: $C) => $D,
183
183
  q5: (_: $D) => $E,
184
184
  q6: (_: $E) => $F,
185
- q7: (_: $F) => QueryProjection<Encoded extends From ? From : never, A, R, TType>
185
+ q7: (_: $F) => QueryProjection<From extends Encoded ? From : never, A, R, TType>
186
186
  ): Effect.Effect<
187
187
  TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
188
188
  | (TType extends "many" ? never : NotFoundError<ItemType>)
@@ -211,7 +211,7 @@ export interface Repository<
211
211
  q5: (_: $D) => $E,
212
212
  q6: (_: $E) => $F,
213
213
  q7: (_: $F) => $G,
214
- q8: (_: $G) => QueryProjection<Encoded extends From ? From : never, A, R, TType>
214
+ q8: (_: $G) => QueryProjection<From extends Encoded ? From : never, A, R, TType>
215
215
  ): Effect.Effect<
216
216
  TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
217
217
  | (TType extends "many" ? never : NotFoundError<ItemType>)
@@ -242,7 +242,7 @@ export interface Repository<
242
242
  q6: (_: $E) => $F,
243
243
  q7: (_: $F) => $G,
244
244
  q8: (_: $G) => $H,
245
- q9: (_: $H) => QueryProjection<Encoded extends From ? From : never, A, R, TType>
245
+ q9: (_: $H) => QueryProjection<From extends Encoded ? From : never, A, R, TType>
246
246
  ): Effect.Effect<
247
247
  TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
248
248
  | (TType extends "many" ? never : NotFoundError<ItemType>)
@@ -275,7 +275,7 @@ export interface Repository<
275
275
  q7: (_: $F) => $G,
276
276
  q8: (_: $G) => $H,
277
277
  q9: (_: $H) => $I,
278
- q10: (_: $I) => QueryProjection<Encoded extends From ? From : never, A, R, TType>
278
+ q10: (_: $I) => QueryProjection<From extends Encoded ? From : never, A, R, TType>
279
279
  ): Effect.Effect<
280
280
  TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
281
281
  | (TType extends "many" ? never : NotFoundError<ItemType>)
@@ -510,7 +510,27 @@ export interface Repository<
510
510
  readonly mapped: Mapped<Encoded>
511
511
  }
512
512
 
513
- export type RefineTHelper<T, EncodedRefined> = EncodedRefined extends { _tag: any }
514
- ? T extends { _tag: any } ? Extract<T, { _tag: EncodedRefined["_tag"] }>
513
+ type NullableRefined<T, EncodedRefined> = {
514
+ // EncodedRefined may be a union, so if you just keyof you'll get just common keys
515
+ // p.s. NullableRefined is homomorphic in T so it distributes itself over T
516
+ [k in keyof T]: [null] extends [T[k]] ? [null] extends Extract<EncodedRefined, { [j in k]: any }>[k] ? T[k]
517
+ : Exclude<T[k], null>
518
+ : T[k]
519
+ }
520
+
521
+ type ExtractTagged<T, EncodedRefined> = EncodedRefined extends { _tag: string }
522
+ ? T extends { _tag: string } ? Extract<T, { _tag: EncodedRefined["_tag"] }>
523
+ : T
524
+ : T
525
+
526
+ type ExtractIded<T, EncodedRefined> = EncodedRefined extends { id: string }
527
+ ? T extends { id: string } ? Extract<T, { id: EncodedRefined["id"] }>
515
528
  : T
516
529
  : T
530
+
531
+ export type RefineTHelper<T, EncodedRefined> = ResolveFirstLevel<
532
+ NullableRefined<
533
+ ExtractIded<ExtractTagged<T, EncodedRefined>, EncodedRefined>,
534
+ EncodedRefined
535
+ >
536
+ >
@@ -1,5 +1,7 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { expectTypeOf } from "@effect/vitest"
1
3
  import type { FieldValues } from "../fields.js"
2
- import type { BrowserNativeObject, Primitive } from "../utils.js"
4
+ import type { BrowserNativeObject, Equals, IsLiteral, IsNever, Primitive } from "../utils.js"
3
5
 
4
6
  import type { ArrayKey, IsTuple, TupleKeys } from "./common.js"
5
7
 
@@ -33,39 +35,6 @@ export type Path<T> = T extends ReadonlyArray<infer V> ? IsTuple<T> extends true
33
35
  */
34
36
  export type FieldPath<TFieldValues extends FieldValues> = Path<TFieldValues>
35
37
 
36
- /**
37
- * Helper type for recursively constructing paths through a type.
38
- * See {@link ArrayPath}
39
- */
40
- type ArrayPathImpl<K extends string | number, V> = V extends
41
- | Primitive
42
- | BrowserNativeObject ? never
43
- : V extends ReadonlyArray<infer U> ? U extends Primitive | BrowserNativeObject ? never
44
- : `${K}` | `${K}.${ArrayPath<V>}`
45
- : `${K}.${ArrayPath<V>}`
46
-
47
- /**
48
- * Type which eagerly collects all paths through a type which point to an array
49
- * type.
50
- * @typeParam T - type which should be introspected
51
- * @example
52
- * ```
53
- * Path<{foo: {bar: string[], baz: number[]}}> = 'foo.bar' | 'foo.baz'
54
- * ```
55
- */
56
- export type ArrayPath<T> = T extends ReadonlyArray<infer V> ? IsTuple<T> extends true ? {
57
- [K in TupleKeys<T>]-?: ArrayPathImpl<K & string, T[K]>
58
- }[TupleKeys<T>]
59
- : ArrayPathImpl<ArrayKey, V>
60
- : {
61
- [K in keyof T]-?: ArrayPathImpl<K & string, T[K]>
62
- }[keyof T]
63
-
64
- /**
65
- * See {@link ArrayPath}
66
- */
67
- export type FieldArrayPath<TFieldValues extends FieldValues> = ArrayPath<TFieldValues>
68
-
69
38
  /**
70
39
  * Type to evaluate the type which the given path points to.
71
40
  * @typeParam T - deeply nested type which is indexed by the path
@@ -76,17 +45,28 @@ export type FieldArrayPath<TFieldValues extends FieldValues> = ArrayPath<TFieldV
76
45
  * PathValue<[number, string], '1'> = string
77
46
  * ```
78
47
  */
79
- export type PathValue<T, P extends Path<T> | ArrayPath<T>> = T extends any
80
- ? P extends `${infer K}.${infer R}` ? K extends keyof T ? R extends Path<T[K]> ? PathValue<T[K], R>
81
- : never
82
- : K extends `${ArrayKey}` ? T extends ReadonlyArray<infer V> ? PathValue<V, R & Path<V>>
83
- : never
84
- : never
85
- : P extends keyof T ? T[P]
86
- : P extends `${ArrayKey}` ? T extends ReadonlyArray<infer V> ? V
48
+ /* dprint-ignore-start */
49
+ export type PathValue<T, P extends Path<T>> =
50
+ T extends any
51
+ ? P extends `${infer K}.${infer R}`
52
+ ? K extends keyof T
53
+ ? R extends Path<T[K]>
54
+ ? PathValue<T[K], R>
55
+ : never
56
+ : K extends `${ArrayKey}`
57
+ ? T extends ReadonlyArray<infer V>
58
+ ? PathValue<V, R & Path<V>>
59
+ : never
60
+ : never
61
+ : P extends keyof T
62
+ ? T[P]
63
+ : P extends `${ArrayKey}`
64
+ ? T extends ReadonlyArray<infer V>
65
+ ? V
66
+ : never
67
+ : never
87
68
  : never
88
- : never
89
- : never
69
+ /* dprint-ignore-end */
90
70
 
91
71
  /**
92
72
  * See {@link PathValue}
@@ -96,13 +76,165 @@ export type FieldPathValue<
96
76
  TFieldPath extends FieldPath<TFieldValues>
97
77
  > = PathValue<TFieldValues, TFieldPath>
98
78
 
99
- /**
100
- * See {@link PathValue}
101
- */
102
- export type FieldArrayPathValue<
79
+ /* dprint-ignore-start */
80
+ export type SetPathValue<T, P extends Path<T>, X> =
81
+ T extends any
82
+ ? P extends `${infer K}.${infer R}`
83
+ ? K extends keyof T
84
+ ? R extends Path<T[K]>
85
+ ? { [_ in keyof T]: _ extends K ? SetPathValue<T[K], R, X> : T[_] }
86
+ : never
87
+ : K extends `${ArrayKey}`
88
+ ? T extends ReadonlyArray<infer V>
89
+ ? { [_ in keyof T]: SetPathValue<V, R & Path<V>, X> }
90
+ : never
91
+ : never
92
+ : P extends keyof T
93
+ ? { [_ in keyof T]: _ extends P ? X : T[_] }
94
+ : P extends `${ArrayKey}`
95
+ ? T extends ReadonlyArray<any>
96
+ ? { [_ in keyof T]: X }
97
+ : never
98
+ : never
99
+ : never
100
+ /* dprint-ignore-end */
101
+
102
+ export type SetFieldPathValue<
103
103
  TFieldValues extends FieldValues,
104
- TFieldArrayPath extends FieldArrayPath<TFieldValues>
105
- > = PathValue<TFieldValues, TFieldArrayPath>
104
+ TFieldPath extends FieldPath<TFieldValues>,
105
+ X
106
+ > = SetPathValue<TFieldValues, TFieldPath, X>
107
+
108
+ /* dprint-ignore-start */
109
+ export type RefinePathValue<T, P extends Path<T>, X extends string | number | boolean | null | bigint, Exclde extends boolean = false> =
110
+ T extends any
111
+ // recursive cases
112
+ ? P extends `${infer K}.${infer R}`
113
+ ? K extends keyof T
114
+ ? R extends Path<T[K]>
115
+ ? { [_ in keyof T]: _ extends K ? RefinePathValue<T[K], R, X, Exclde> : T[_] }
116
+ : never
117
+ : K extends `${ArrayKey}`
118
+ ? T extends ReadonlyArray<infer V>
119
+ ? { [_ in keyof T]: RefinePathValue<V, R & Path<V>, X, Exclde> }
120
+ : never
121
+ : never
122
+ // base cases
123
+ : P extends keyof T
124
+ ? X extends T[P]
125
+ ? ({ [_ in keyof T]: _ extends P
126
+ ? Equals<
127
+ Exclde,
128
+ true,
129
+ Exclude<T[_], X>,
130
+ IsLiteral<T[_], X, Equals<X, null, null, NonNullable<T[_]>>>
131
+ >
132
+ : T[_]
133
+ }) extends infer $T
134
+ ? Equals<IsNever<$T[P & keyof $T]>, true, never, $T>
135
+ : never
136
+ : Equals<Exclde, true, T, never>
137
+ : P extends `${ArrayKey}`
138
+ ? T extends ReadonlyArray<infer V>
139
+ ? X extends V
140
+ ? { [_ in keyof T]: Equals<
141
+ Exclde,
142
+ true,
143
+ Exclude<T[_], X>,
144
+ IsLiteral<T[_], X, Equals<X, null, null, NonNullable<T[_]>>>
145
+ > }
146
+ : never
147
+ : never
148
+ : never
149
+ : never
150
+ /* dprint-ignore-end */
151
+
152
+ export type RefineFieldPathValue<
153
+ TFieldValues extends FieldValues,
154
+ TFieldPath extends FieldPath<TFieldValues>,
155
+ X extends string | number | boolean | null | bigint,
156
+ Exclde extends boolean = false
157
+ > = RefinePathValue<TFieldValues, TFieldPath, X, Exclde>
158
+
159
+ export namespace RefinePathValueTests {
160
+ type test1 = RefineFieldPathValue<{ a: { b: "tag1"; v1: string } | { b: "tag2"; v2: number } }, "a.b", "tag1">
161
+ expectTypeOf<test1>().toEqualTypeOf<{ a: { b: "tag1"; v1: string } }>()
162
+
163
+ type test2 = RefineFieldPathValue<{ b: "tag1"; v1: string } | { b: "tag2"; v2: number }, "b", "tag1">
164
+ expectTypeOf<test2>().toEqualTypeOf<{ b: "tag1"; v1: string }>()
165
+
166
+ type test3 = RefineFieldPathValue<{ b: "tag1" | "tag2" }, "b", "tag1">
167
+ expectTypeOf<test3>().toEqualTypeOf<{ b: "tag1" }>()
168
+
169
+ type test4 = RefineFieldPathValue<{ b: ("tag1" | "tag2")[] }, `b.${number}`, "tag1">
170
+ expectTypeOf<test4>().toEqualTypeOf<{ b: "tag1"[] }>()
171
+
172
+ type test5 = RefineFieldPathValue<{ b: "tag1"; v1: unknown } | { b: "tag2"; v2: unknown }, "b", "tag1">
173
+ expectTypeOf<test5>().toEqualTypeOf<{ b: "tag1"; v1: unknown }>()
174
+
175
+ type test6 = RefineFieldPathValue<
176
+ { a: { b: "tag1"; v1: string } | { b: "tag2"; v2: number } } | { something: "else " },
177
+ "a.b",
178
+ "tag2"
179
+ >
180
+ expectTypeOf<test6>().toEqualTypeOf<{ a: { b: "tag2"; v2: number } }>()
181
+
182
+ type test7 = RefineFieldPathValue<{ b: string | null }, "b", "tag1">
183
+ expectTypeOf<test7>().toEqualTypeOf<{ b: string }>()
184
+
185
+ type test8 = RefineFieldPathValue<{ b: string | null }, "b", null>
186
+ expectTypeOf<test8>().toEqualTypeOf<{ b: null }>()
187
+
188
+ type test1E = RefineFieldPathValue<{ a: { b: "tag1"; v1: string } | { b: "tag2"; v2: number } }, "a.b", "tag1", true>
189
+ expectTypeOf<test1E>().toEqualTypeOf<{ a: { b: "tag2"; v2: number } }>()
190
+
191
+ type test2E = RefineFieldPathValue<{ b: "tag1"; v1: string } | { b: "tag2"; v2: number }, "b", "tag2", true>
192
+ expectTypeOf<test2E>().toEqualTypeOf<{ b: "tag1"; v1: string }>()
193
+
194
+ type test3E = RefineFieldPathValue<{ b: "tag1" | "tag2" | null }, "b", null, true>
195
+ expectTypeOf<test3E>().toEqualTypeOf<{ b: "tag1" | "tag2" }>()
196
+
197
+ type test4E = RefineFieldPathValue<{ b: ("tag1" | "tag2")[] }, `b.${number}`, "tag1", true>
198
+ expectTypeOf<test4E>().toEqualTypeOf<{ b: "tag2"[] }>()
199
+
200
+ type test5E = RefineFieldPathValue<{ b: "tag1"; v1: unknown } | { b: "tag2"; v2: unknown }, "b", "tag1", true>
201
+ expectTypeOf<test5E>().toEqualTypeOf<{ b: "tag2"; v2: unknown }>()
202
+
203
+ type test6E = RefineFieldPathValue<
204
+ { a: { b: "tag1"; v1: string } | { b: "tag2"; v2: number } } | { something: "else " },
205
+ "a.b",
206
+ "tag2",
207
+ true
208
+ >
209
+ expectTypeOf<test6E>().toEqualTypeOf<{ a: { b: "tag1"; v1: string } }>()
210
+ }
211
+
212
+ export namespace SetFieldPathValueTests {
213
+ type test1 = SetFieldPathValue<{ foo: { bar: string[] } }, `foo.bar`, boolean>
214
+ expectTypeOf<test1>().toEqualTypeOf<{ foo: { bar: boolean } }>()
215
+
216
+ type test1a = SetFieldPathValue<{ foo: { bar: string[]; baz: 12 } }, `foo.bar`, boolean>
217
+ expectTypeOf<test1a>().toEqualTypeOf<{ foo: { bar: boolean; baz: 12 } }>()
218
+
219
+ type test2 = SetFieldPathValue<{ foo: { bar: string[] } }, `foo.bar.${number}`, boolean>
220
+ expectTypeOf<test2>().toEqualTypeOf<{ foo: { bar: boolean[] } }>()
221
+
222
+ type test2a = SetFieldPathValue<{ foo: { bar: readonly string[]; baz: 3 }; ban: 123 }, `foo.bar.${number}`, boolean>
223
+ expectTypeOf<test2a>().toEqualTypeOf<{ foo: { bar: readonly boolean[]; baz: 3 }; ban: 123 }>()
224
+
225
+ type test2b = SetFieldPathValue<
226
+ { foo: { bar: readonly { a: 1; b: 2 }[]; baz: 3 }; ban: 123 },
227
+ `foo.bar.${number}.b`,
228
+ "b"
229
+ >
230
+ expectTypeOf<test2b>().toEqualTypeOf<{ foo: { bar: readonly { a: 1; b: "b" }[]; baz: 3 }; ban: 123 }>()
231
+
232
+ type test3 = SetFieldPathValue<{ foo: ["a", "b"] }, `foo.0`, boolean>
233
+ expectTypeOf<test3>().toEqualTypeOf<{ foo: [boolean, "b"] }>()
234
+
235
+ type test3a = SetFieldPathValue<{ foo: [{ a: 123 }, "b"] }, `foo.0.a`, boolean>
236
+ expectTypeOf<test3a>().toEqualTypeOf<{ foo: [{ a: boolean }, "b"] }>()
237
+ }
106
238
 
107
239
  /**
108
240
  * Type to evaluate the type which the given paths point to.
@@ -1,14 +1,4 @@
1
1
  /** Re-export public API */
2
2
 
3
3
  export type { PathString } from "./common.js"
4
- export type {
5
- ArrayPath,
6
- FieldArrayPath,
7
- FieldArrayPathValue,
8
- FieldPath,
9
- FieldPathByValue,
10
- FieldPathValue,
11
- FieldPathValues,
12
- Path,
13
- PathValue
14
- } from "./eager.js"
4
+ export type { FieldPath, FieldPathByValue, FieldPathValue, FieldPathValues, Path, PathValue } from "./eager.js"
@@ -104,3 +104,25 @@ export type Merge<A, B> = {
104
104
  : K extends keyof B ? B[K]
105
105
  : never
106
106
  }
107
+
108
+ export type Resolve<T> =
109
+ & {
110
+ [K in keyof T]: Resolve<T[K]>
111
+ }
112
+ & unknown
113
+
114
+ export type ResolveFirstLevel<T> =
115
+ & {
116
+ [K in keyof T]: T[K]
117
+ }
118
+ & unknown
119
+
120
+ export type Cast<T, U> = T extends U ? T : U
121
+
122
+ export type IsLiteral<T, True, False> = string extends T ? False : number extends T ? False : True
123
+
124
+ export type Extends<T, U, True, False> = T extends U ? True : False
125
+
126
+ export type IsEqual<T, U> = (<_>() => _ extends T ? 1 : 2) extends (<_>() => _ extends U ? 1 : 2) ? true : false
127
+
128
+ export type Equals<T, U, True, False> = IsEqual<T, U> extends true ? True : False