@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.
- package/CHANGELOG.md +12 -0
- package/_cjs/Model/filter/types/path/eager.cjs +31 -0
- package/_cjs/Model/filter/types/path/eager.cjs.map +1 -1
- package/_cjs/Model/query/dsl.cjs.map +1 -1
- package/_cjs/api/routing copy.cjs +196 -0
- package/_cjs/api/routing copy.cjs.map +1 -0
- package/_cjs/api/routing.cjs +2 -1
- package/_cjs/api/routing.cjs.map +1 -1
- package/dist/Model/Repository/ext.d.ts +3 -3
- package/dist/Model/Repository/service.d.ts +28 -14
- package/dist/Model/Repository/service.d.ts.map +1 -1
- package/dist/Model/filter/types/path/eager.d.ts +26 -29
- package/dist/Model/filter/types/path/eager.d.ts.map +1 -1
- package/dist/Model/filter/types/path/eager.js +30 -2
- package/dist/Model/filter/types/path/index.d.ts +1 -1
- package/dist/Model/filter/types/path/index.d.ts.map +1 -1
- package/dist/Model/filter/types/utils.d.ts +11 -0
- package/dist/Model/filter/types/utils.d.ts.map +1 -1
- package/dist/Model/query/dsl.d.ts +23 -16
- package/dist/Model/query/dsl.d.ts.map +1 -1
- package/dist/Model/query/dsl.js +1 -1
- package/dist/Model/query/new-kid-interpreter.d.ts +1 -1
- package/dist/QueueMaker/sbqueue.d.ts +2 -2
- package/dist/Store/service.d.ts +1 -1
- package/dist/api/routing copy.d.ts +160 -0
- package/dist/api/routing copy.d.ts.map +1 -0
- package/dist/api/routing copy.js +210 -0
- package/dist/api/routing.d.ts +12 -2
- package/dist/api/routing.d.ts.map +1 -1
- package/dist/api/routing.js +4 -3
- package/examples/query.ts +35 -3
- package/package.json +1 -1
- package/src/Model/Repository/service.ts +33 -13
- package/src/Model/filter/types/path/eager.ts +182 -50
- package/src/Model/filter/types/path/index.ts +1 -11
- package/src/Model/filter/types/utils.ts +22 -0
- package/src/Model/query/dsl.ts +314 -30
- package/src/api/routing.ts +159 -77
- package/test/controller.test.ts +151 -0
- package/test/dist/controller.test copy.js +129 -0
- package/test/dist/controller.test.d.ts.map +1 -0
- package/test/dist/controller5.test.d.ts.map +1 -0
- 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
|
@@ -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<
|
|
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<
|
|
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<
|
|
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<
|
|
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<
|
|
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<
|
|
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<
|
|
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<
|
|
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<
|
|
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<
|
|
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
|
-
|
|
514
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
|
|
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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
|
|
105
|
-
|
|
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
|