1- import type { conform } from "@arktype/util"
1+ import type { conform , leftIfEqual } from "@arktype/util"
22import type { PrimitiveConstraintKind } from "./constraint.js"
33import type { NodeSchema } from "./kinds.js"
44import type { constraintKindOf } from "./roots/intersection.js"
5+ import type { MorphAst , Out } from "./roots/morph.js"
56
67export type Comparator = "<" | "<=" | ">" | ">=" | "=="
78
@@ -126,6 +127,11 @@ export type LessThanLength<rule extends number> = {
126127 max : { [ k in rule ] : 0 }
127128}
128129
130+ export type ExactlyLength < rule extends number > = {
131+ min : { [ k in rule ] : 1 }
132+ max : { [ k in rule ] : 1 }
133+ }
134+
129135export namespace string {
130136 export type atLeastLength < rule extends number > = of <
131137 string ,
@@ -144,6 +150,11 @@ export namespace string {
144150 LessThanLength < rule >
145151 >
146152
153+ export type exactlyLength < rule extends number > = of <
154+ string ,
155+ ExactlyLength < rule >
156+ >
157+
147158 export type matching < rule extends string > = of < string , Matching < rule > >
148159
149160 export type narrowed = of < string , Narrowed >
@@ -164,6 +175,7 @@ export namespace string {
164175 lessThanLength < rule & number >
165176 : atMostLength < rule & number >
166177 : kind extends "regex" ? matching < rule & string >
178+ : kind extends "exactLength" ? exactlyLength < rule & number >
167179 : narrowed
168180 : never
169181}
@@ -227,11 +239,9 @@ export type constrain<
227239 kind extends PrimitiveConstraintKind ,
228240 schema extends NodeSchema < kind >
229241> =
230- _constrain < t , kind , schema > extends infer constrained ?
231- [ t , constrained ] extends [ constrained , t ] ?
232- t
233- : constrained
234- : never
242+ t extends MorphAst < infer i , infer o > ?
243+ ( In : leftIfEqual < i , _constrain < i , kind , schema > > ) => Out < o >
244+ : leftIfEqual < t , _constrain < t , kind , schema > >
235245
236246type _constrain <
237247 t ,
@@ -282,6 +292,7 @@ export type schemaToConstraint<
282292 schema extends { exclusive : true } ?
283293 LessThanLength < rule & number >
284294 : AtMostLength < rule & number >
295+ : kind extends "exactLength" ? ExactlyLength < rule & number >
285296 : kind extends "after" ?
286297 schema extends { exclusive : true } ?
287298 After < normalizeLimit < rule > >
0 commit comments