Skip to content

Commit a51f3c8

Browse files
committed
Dependent If Type
1 parent 1d1006e commit a51f3c8

7 files changed

Lines changed: 115 additions & 2 deletions

File tree

design/syntax/syntax.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ const Base = Runtime.Union([
283283
Runtime.Ref('Constructor'),
284284
Runtime.Ref('_Function_'),
285285
Runtime.Ref('Mapped'),
286+
Runtime.Ref('_If_'),
286287
Runtime.Ref('Options'),
287288
Runtime.Ref('GenericCall'),
288289
Runtime.Ref('Reference')
@@ -638,6 +639,14 @@ const Mapped = Runtime.Tuple([
638639
Runtime.Const(RBrace),
639640
])
640641
// ------------------------------------------------------------------
642+
// If
643+
// ------------------------------------------------------------------
644+
const _If_ = Runtime.Union([
645+
Runtime.Tuple([Runtime.Const('if'), Runtime.Ref('Type'), Runtime.Const('then'), Runtime.Ref('Type'), Runtime.Const('else'), Runtime.Ref('Type')]),
646+
Runtime.Tuple([Runtime.Const('if'), Runtime.Ref('Type'), Runtime.Const('then'), Runtime.Ref('Type')]),
647+
Runtime.Tuple([Runtime.Const('if'), Runtime.Ref('Type'), Runtime.Const('else'), Runtime.Ref('Type')])
648+
])
649+
// ------------------------------------------------------------------
641650
// Options
642651
// ------------------------------------------------------------------
643652
const Options = Runtime.Tuple([
@@ -1008,6 +1017,9 @@ export const SyntaxModule = new Runtime.Module({
10081017
MappedOptional,
10091018
MappedAs,
10101019
Mapped,
1020+
1021+
_If_,
1022+
10111023
Reference,
10121024
Options,
10131025

src/type/script/mapping.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,25 @@ export function MappedMapping(input: [unknown, unknown, unknown, unknown, unknow
12081208
)
12091209
}
12101210
// -------------------------------------------------------------------
1211+
// _If_: ['if', Type, 'then', Type, 'else', Type] | ['if', Type, 'then', Type] | ['if', Type, 'else', Type]
1212+
// -------------------------------------------------------------------
1213+
export type T_If_Mapping<Input extends [unknown, unknown, unknown, unknown, unknown, unknown] | [unknown, unknown, unknown, unknown]> = (
1214+
Input extends ['if', infer If extends T.TSchema, 'then', infer Then extends T.TSchema, 'else', infer Else extends T.TSchema]
1215+
? T.TIf<If, Then, Else> :
1216+
Input extends ['if', infer If extends T.TSchema, 'then', infer Then extends T.TSchema]
1217+
? T.TIf<If, Then, T.TNever> :
1218+
Input extends ['if', infer If extends T.TSchema, 'else', infer Else extends T.TSchema]
1219+
? T.TIf<If, T.TNever, Else> :
1220+
never
1221+
)
1222+
export function _If_Mapping(input: [unknown, unknown, unknown, unknown, unknown, unknown] | [unknown, unknown, unknown, unknown]): unknown {
1223+
return (
1224+
Guard.IsEqual(input.length, 6) ? T.If(input[1] as T.TSchema, input[3] as T.TSchema, input[5] as T.TSchema) :
1225+
Guard.IsEqual(input[2], 'then') ? T.If(input[1] as T.TSchema, input[3] as T.TSchema, T.Never()) :
1226+
T.If(input[1] as T.TSchema, T.Never(), input[3] as T.TSchema)
1227+
)
1228+
}
1229+
// -------------------------------------------------------------------
12111230
// Reference: <Ident>
12121231
// -------------------------------------------------------------------
12131232
export type TReferenceMapping<Input extends string,

src/type/script/parser.ts

Lines changed: 4 additions & 2 deletions
Large diffs are not rendered by default.

src/type/types/if.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*--------------------------------------------------------------------------
2+
3+
TypeBox
4+
5+
The MIT License (MIT)
6+
7+
Copyright (c) 2017-2026 Haydn Paterson
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy
10+
of this software and associated documentation files (the "Software"), to deal
11+
in the Software without restriction, including without limitation the rights
12+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
copies of the Software, and to permit persons to whom the Software is
14+
furnished to do so, subject to the following conditions:
15+
16+
The above copyright notice and this permission notice shall be included in
17+
all copies or substantial portions of the Software.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
THE SOFTWARE.
26+
27+
---------------------------------------------------------------------------*/
28+
29+
// deno-fmt-ignore-file
30+
31+
import { Memory } from '../../system/memory/index.ts'
32+
import { type StaticType, type StaticDirection } from './static.ts'
33+
import { type TSchema, type TSchemaOptions, IsKind } from './schema.ts'
34+
import { type TProperties } from './properties.ts'
35+
36+
// ------------------------------------------------------------------
37+
// Static
38+
// ------------------------------------------------------------------
39+
export type StaticIf<Stack extends string[], Direction extends StaticDirection, Context extends TProperties, This extends TProperties, If extends TSchema, Then extends TSchema, Else extends TSchema,
40+
StaticIf extends unknown = StaticType<Stack, Direction, Context, This, If>,
41+
StaticThen extends unknown = StaticType<Stack, Direction, Context, This, Then>,
42+
StaticElse extends unknown = StaticType<Stack, Direction, Context, This, Else>,
43+
Result extends unknown = (StaticIf & StaticThen) | Exclude<StaticElse, StaticIf>
44+
> = Result
45+
// ------------------------------------------------------------------
46+
// Type
47+
// ------------------------------------------------------------------
48+
/** Represents a Conditionally Dependent If Type */
49+
export interface TIf<If extends TSchema = TSchema, Then extends TSchema = TSchema, Else extends TSchema = TSchema> extends TSchema {
50+
'~kind': 'If'
51+
if: If
52+
then: Then
53+
else: Else
54+
}
55+
// ------------------------------------------------------------------
56+
// Factory
57+
// ------------------------------------------------------------------
58+
/** Creates a Conditionally Dependent If Type */
59+
export function If<If extends TSchema, Then extends TSchema, Else extends TSchema>(if_: If, then_: Then, else_: Else, options: TSchemaOptions = {}): TIf<If, Then, Else> {
60+
return Memory.Create({ '~kind': 'If' }, { if: if_, then: then_, else: else_ }, options) as never
61+
}
62+
// ------------------------------------------------------------------
63+
// Guard
64+
// ------------------------------------------------------------------
65+
/** Returns true if the given value is TIf. */
66+
export function IsIf(value: unknown): value is TIf {
67+
return IsKind(value, 'If')
68+
}
69+
70+
// ------------------------------------------------------------------
71+
// Options
72+
// ------------------------------------------------------------------
73+
/** Extracts options from a TIf. */
74+
export function IfOptions(type: TIf): TSchemaOptions {
75+
return Memory.Discard(type, ['~kind', 'if', 'then', 'else'])
76+
}

src/type/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export * from './enum.ts'
5252
export * from './function.ts'
5353
export * from './generic.ts'
5454
export * from './identifier.ts'
55+
export * from './if.ts'
5556
export * from './infer.ts'
5657
export * from './integer.ts'
5758
export * from './intersect.ts'

src/type/types/static.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import type { StaticCyclic, TCyclic } from './cyclic.ts'
4141
import type { StaticEnum, TEnum, TEnumValue } from './enum.ts'
4242
import type { StaticFunction, TFunction } from './function.ts'
4343
import type { StaticInteger, TInteger } from './integer.ts'
44+
import type { StaticIf, TIf } from './if.ts'
4445
import type { StaticIntersect, TIntersect } from './intersect.ts'
4546
import type { StaticIterator, TIterator } from './iterator.ts'
4647
import type { StaticLiteral, TLiteral, TLiteralValue } from './literal.ts'
@@ -89,6 +90,7 @@ export type StaticType<Stack extends string[], Direction extends StaticDirection
8990
Type extends TConstructor<infer Parameters extends TSchema[], infer ReturnType extends TSchema> ? StaticConstructor<Stack, Direction, Context, This, Parameters, ReturnType> :
9091
Type extends TEnum<infer Values extends TEnumValue[]> ? StaticEnum<Values> :
9192
Type extends TFunction<infer Parameters extends TSchema[], infer ReturnType extends TSchema> ? StaticFunction<Stack, Direction, Context, This, Parameters, ReturnType> :
93+
Type extends TIf<infer If extends TSchema, infer Then extends TSchema, infer Else extends TSchema> ? StaticIf<Stack, Direction, Context, This, If, Then, Else> :
9294
Type extends TInteger ? StaticInteger :
9395
Type extends TIntersect<infer Types extends TSchema[]> ? StaticIntersect<Stack, Direction, Context, This, Types> :
9496
Type extends TIterator<infer Types extends TSchema> ? StaticIterator<Stack, Direction, Context, This, Types> :

src/typebox.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ export { Enum, IsEnum, type TEnum, type TEnumValue } from './type/types/enum.ts'
9595
export { Function, IsFunction, type TFunction } from './type/types/function.ts'
9696
export { Generic, IsGeneric, type TGeneric } from './type/types/generic.ts'
9797
export { Identifier, IsIdentifier, type TIdentifier } from './type/types/identifier.ts'
98+
export { If, IsIf, type TIf } from './type/types/if.ts'
9899
export { Infer, IsInfer, type TInfer } from './type/types/infer.ts'
99100
export { Integer, IsInteger, type TInteger } from './type/types/integer.ts'
100101
export { Intersect, IsIntersect, type TIntersect } from './type/types/intersect.ts'

0 commit comments

Comments
 (0)