Skip to content

Commit 38ba55d

Browse files
authored
Version 1.0.78 (#1514)
* Exclude If on Else Arm for Conditional Schema * Test * ChangeLog * Version
1 parent eea5e87 commit 38ba55d

4 files changed

Lines changed: 91 additions & 23 deletions

File tree

changelog/1.0.0.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
---
44

55
### Version Updates
6+
- [Revision 1.0.78](https://github.com/sinclairzx81/typebox/pull/1514)
7+
- Exclude If on Else Arm for Conditional Schema
68
- [Revision 1.0.77](https://github.com/sinclairzx81/typebox/pull/1512)
79
- Fix TemplateLiteral Infinite Expansion in Value Processors
810
- [Revision 1.0.76](https://github.com/sinclairzx81/typebox/pull/1509)

src/schema/static/if.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,17 @@ import type { XIf } from '../types/if.ts'
3434
import type { XElse } from '../types/else.ts'
3535
import type { XThen } from '../types/then.ts'
3636

37-
type XStaticIfReduce<Types extends unknown[], Result extends unknown = never> = (
38-
Types extends [infer Left extends unknown, ...infer Right extends unknown[]]
39-
? XStaticIfReduce<Right, Result | Left>
40-
: Result
41-
)
4237
export type XStaticIf<Stack extends string[], Root extends XSchema, Schema extends XIf, IfSchema extends XSchema,
43-
Then extends unknown[] = Schema extends XThen<infer ThenSchema extends XSchema> ? [XStaticSchema<Stack, Root, IfSchema> & XStaticSchema<Stack, Root, ThenSchema>] : [],
44-
Else extends unknown[] = Schema extends XElse<infer ElseSchema extends XSchema> ? [...Then, XStaticSchema<Stack, Root, ElseSchema>] : Then,
45-
Result extends unknown = Else extends [] ? unknown : XStaticIfReduce<Else>
46-
> = Result
38+
If extends unknown = XStaticSchema<Stack, Root, IfSchema>,
39+
Then extends unknown = Schema extends XThen<infer ThenSchema extends XSchema> ? XStaticSchema<Stack, Root, ThenSchema> : never,
40+
Else extends unknown = Schema extends XElse<infer ElseSchema extends XSchema> ? XStaticSchema<Stack, Root, ElseSchema> : never,
41+
42+
IsThen extends boolean = Schema extends XThen ? true : false,
43+
IsElse extends boolean = Schema extends XElse ? true : false,
44+
Result extends unknown = (
45+
[IsThen, IsElse] extends [true, true] ? (If & Then) | Exclude<Else, If> :
46+
[IsThen, IsElse] extends [true, false] ? (If & Then) :
47+
[IsThen, IsElse] extends [false, true] ? Exclude<Else, If> :
48+
unknown
49+
)
50+
> = Result

tasks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Range } from './task/range/index.ts'
88
import { Metrics } from './task/metrics/index.ts'
99
import { Task } from 'tasksmith'
1010

11-
const Version = '1.0.77'
11+
const Version = '1.0.78'
1212

1313
// ------------------------------------------------------------------
1414
// Build

test/typebox/static/schema/if.ts

Lines changed: 75 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
import { Assert } from 'test'
22
import { type XStatic } from 'typebox/schema'
33

4-
// if does not contribute to inference
4+
// 'if' alone does not contribute to inference
55
Assert.IsExtendsMutual<
66
XStatic<{
77
if: { type: 'number' }
88
}>,
99
unknown
1010
>(true)
11-
// else/then do not contribute if "if" clause is absent
11+
// 'else/then' do not contribute if "if" clause not present
1212
Assert.IsExtendsMutual<
1313
XStatic<{
1414
else: { const: 1 }
1515
then: { const: 2 }
1616
}>,
1717
unknown
1818
>(true)
19-
// if/then should narrow as (if & then)
19+
// 'if/then' should narrow as (if & then)
2020
Assert.IsExtendsMutual<
2121
XStatic<{
2222
if: { type: 'number' }
@@ -70,33 +70,95 @@ Assert.IsExtendsMutual<
7070
Assert.IsExtendsMutual<
7171
XStatic<{
7272
if: { type: 'number' }
73-
else: {
74-
if: { type: 'number' }
75-
else: { const: 1 }
76-
then: { const: 2 }
77-
}
7873
then: {
7974
if: { type: 'number' }
8075
else: { const: 3 }
8176
then: { const: 4 }
8277
}
78+
else: {
79+
if: { type: 'number' }
80+
else: { const: 1 }
81+
then: { const: 2 }
82+
}
8383
}>,
84-
1 | 2 | 3 | 4
84+
4
8585
>(true)
8686
// multi variant nested if/then/else inference
8787
Assert.IsExtendsMutual<
8888
XStatic<{
8989
if: { type: ['number', 'string'] }
90+
then: {
91+
if: { type: 'string' }
92+
else: { const: 'A' }
93+
then: { const: 'B' }
94+
}
9095
else: {
9196
if: { type: 'number' }
9297
else: { const: 1 }
9398
then: { const: 2 }
9499
}
100+
}>,
101+
'B'
102+
>(true)
103+
// when else arm unreachable, so we evaluate for then only
104+
Assert.IsExtendsMutual<
105+
XStatic<{
106+
if: { type: 'number' }
107+
then: { const: 1 }
108+
else: { const: 2 } // anything reaching else would NOT be number, thus
109+
// could never satisfy the constraint of 2.
110+
}>,
111+
1
112+
>(true)
113+
// when else arm is reachable.
114+
Assert.IsExtendsMutual<
115+
XStatic<{
116+
if: { type: 'number' }
117+
then: { const: 1 }
118+
else: { const: 'hello' } // anything NOT number is reachable
119+
}>,
120+
1 | 'hello'
121+
>(true)
122+
// when if arm is illogical, infer as else.
123+
Assert.IsExtendsMutual<
124+
XStatic<{
125+
if: { type: 'string' }
126+
then: { const: 1 } // illogical
127+
else: { const: 2 }
128+
}>,
129+
2
130+
>(true)
131+
// should be distributive over union
132+
Assert.IsExtendsMutual<
133+
XStatic<{
134+
type: 'object'
135+
required: ['x']
136+
properties: {
137+
x: { type: 'number' }
138+
}
139+
if: {
140+
properties: {
141+
x: { const: 1 }
142+
}
143+
}
95144
then: {
96-
if: { type: 'string' }
97-
else: { const: 'A' }
98-
then: { const: 'B' }
145+
required: ['y']
146+
properties: {
147+
y: { const: 2 }
148+
}
149+
}
150+
else: {
151+
required: ['z']
152+
properties: {
153+
z: { const: 3 }
154+
}
99155
}
100156
}>,
101-
1 | 2 | 'A' | 'B'
157+
{
158+
z: 3
159+
x: number
160+
} | {
161+
x: 1
162+
y: 2
163+
}
102164
>(true)

0 commit comments

Comments
 (0)