Skip to content

Commit

Permalink
fix(and): fixing typing for and
Browse files Browse the repository at this point in the history
  • Loading branch information
mirek committed Jan 29, 2024
1 parent 4e4b4f5 commit 3013aad
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 8 deletions.
36 changes: 33 additions & 3 deletions src/and.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,39 @@
import * as $ from './index.js'

test('and', () => {
const r: { name: string } = $.and(
$.object({ firstName: $.nullishOr($.string), lastName: $.nullishOr($.string), name: $.string }),
const r = $.and(
$.object({ firstName: $.nullishOr($.string), lastName: $.nullishOr($.string), name: $.unknown }),
$.object({ name: $.string })
)(JSON.parse('{"name":"Foo","role":"admin"}'))
expect(r).toEqual({ name: 'Foo', role: 'admin' })
const name: string = r.name
expect(name).toEqual('Foo')
})

test('parametric', () => {
const known = {
string: $.string,
number: $.number
} as const
const assertType = $.oneOf(
'string',
'number'
)
const assertUnknown = $.exact({
type: assertType,
value: $.unknown
})
const assert =
<T extends undefined | 'number' | 'string'>(type: T) =>
$.and(
assertUnknown,
value =>
$.object({
type: $.eq(type ?? value.type),
value: known[type ?? value.type]
})(value)
)
assert('number')(JSON.parse('{"type":"number","value":42}'))
expect(() => assert('number')(JSON.parse('{"type":"number","value":"42"}'))).toThrow()
assert('string')(JSON.parse('{"type":"string","value":"42"}'))
expect(() => assert('string')(JSON.parse('{"type":"string","value":42}'))).toThrow()
})
12 changes: 7 additions & 5 deletions src/and.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import type { Assert } from './prelude.js'

type $<T> = Assert<T>
type Z<A, B> =
(value: A) =>
B

type And = {
<A>(a: $<A>): $<A>
<A, B>(a: $<A>, b: $<B>): $<A & B>
<A, B, C>(a: $<A>, b: $<B>, c: $<C>): $<A & B & C>
<A, B, C, D>(a: $<A>, b: $<B>, c: $<C>, d: $<D>): $<A & B & C & D>
<A>(a: Assert<A>): Assert<A>
<A, B>(a: Assert<A>, b: Z<A, B>): Assert<A & B>
<A, B, C>(a: Assert<A>, b: Z<A, B>, c: Z<B, C>): Assert<A & B & C>
<A, B, C, D>(a: Assert<A>, b: Z<A, B>, c: Z<B, C>, d: Z<C, D>): Assert<A & B & C & D>
}

const and: And =
Expand Down

0 comments on commit 3013aad

Please sign in to comment.