Skip to content

Commit

Permalink
allow booleans as type discriminators
Browse files Browse the repository at this point in the history
fixes #98
  • Loading branch information
hoeck committed May 9, 2023
1 parent e447a3b commit c630956
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 4 deletions.
12 changes: 9 additions & 3 deletions src/union.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function internalDiscriminatedUnion(
key: string,
runtypes: Runtype<any>[],
): Runtype<any> {
const typeMap = new Map<string | number, Runtype<any>>()
const typeMap = new Map<string | number | boolean, Runtype<any>>()

// build an index for fast runtype lookups by literal
runtypes.forEach((t: any) => {
Expand All @@ -37,9 +37,15 @@ function internalDiscriminatedUnion(
)
}

if (!(typeof tagValue === 'string' || typeof tagValue === 'number')) {
if (
!(
typeof tagValue === 'string' ||
typeof tagValue === 'number' ||
typeof tagValue === 'boolean'
)
) {
throw new RuntypeUsageError(
`broken record type definition, ${t}[${key}] must be a string or number, not ${debugValue(
`broken record type definition, ${t}[${key}] must be a literal, not ${debugValue(
tagValue,
)}`,
)
Expand Down
45 changes: 44 additions & 1 deletion test/union.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe('union', () => {
})
})

describe('discriminatedUnion', () => {
describe('discriminated union', () => {
enum Tag {
A = 'a_tag',
B = 'b_tag',
Expand Down Expand Up @@ -129,4 +129,47 @@ describe('discriminatedUnion', () => {
),
])
})

it('should allow numbers and booleans as discrimination literals too', () => {
const runtype = st.union(
st.record({
type: st.literal(1),
number: st.number(),
}),
st.record({ type: st.literal(true), boolean: st.boolean() }),
st.record({ type: st.literal('a'), string: st.string() }),
)

expectAcceptValuesPure(runtype, [
{ type: 1, number: 2 },
{ type: true, boolean: false },
{ type: 'a', string: 'b' },
])

expectRejectValues(runtype, [
// incorrect type
{ type: 1, number: 'foo' },
{ type: 1, boolean: false },
{ type: true, boolean: 1 },
{ type: true, boolean: false, number: 1 },
{ type: 'a', number: 1 },
{ type: 'a', string: 'a', boolean: false, number: 1 },
{ type: 'a', string: false },
// non-existing type discriminator
{ type: 2 },
{ type: 2, number: 2 },
{ type: false, boolean: true },
{ type: false, number: 1 },
{ type: 'b', string: 'a' },
{ type: 'c' },
{ type: '' },
// completely missing type literal
{ type: null },
{ string: 'b' },
{},
{ number: false },
{ boolean: 1 },
{ a: 1 },
])
})
})

0 comments on commit c630956

Please sign in to comment.