Skip to content

Commit

Permalink
feat: arrayOf
Browse files Browse the repository at this point in the history
  • Loading branch information
LuciNyan committed Feb 28, 2023
1 parent 22d4b93 commit 507b763
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 26 deletions.
62 changes: 39 additions & 23 deletions src/operator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest'

import { isBoolean, isNumber, isObject, isString } from './base'
import { make } from './make'
import { and, or, arrayOf } from './operator'
import { and, arrayOf, or } from './operator'

describe('or', () => {
it('should return true if value matches any of the guards', () => {
Expand Down Expand Up @@ -47,31 +47,47 @@ describe('and', () => {
})

describe('arrayOf', () => {
const guard = arrayOf(
isString,
isNumber
)
const guard1 = arrayOf(or(
isString,
isNumber
))
describe('when passed an array of guards', () => {
const guard = arrayOf(isNumber, isString)

it('returns true when passed an array of matching types', () => {
expect(guard([1])).toBe(true)
expect(guard([1, 'hello'])).toBe(true)
expect(guard(['1', 'hello', '1', 'hello'])).toBe(true)
})

it('should return true if value matche', () => {
expect(guard([1])).toBe(true)
expect(guard([1, 2])).toBe(true)
expect(guard(['Luci'])).toBe(true)
expect(guard1([1])).toBe(true)
expect(guard1([1, 2])).toBe(true)
expect(guard1(['Luci'])).toBe(true)
it('returns false when passed an array of non-matching types', () => {
expect(guard([true])).toBe(false)
expect(guard([1, 'hello', true])).toBe(false)
})
})

it('should return false if value does not match', () => {
expect(guard(undefined)).toBe(false)
expect(guard(null)).toBe(false)
expect(guard({ name: 123 })).toBe(false)
expect(guard1(undefined)).toBe(false)
expect(guard1(null)).toBe(false)
expect(guard1({ name: 123 })).toBe(false)
describe('when passed a spread of guards', () => {
const guard = arrayOf(isNumber, isString)

it('returns true when passed an array of matching types', () => {
expect(guard([1])).toBe(true)
expect(guard([1, 'hello'])).toBe(true)
expect(guard(['1', 'hello', '1', 'hello'])).toBe(true)
})

it('returns false when passed an array of non-matching types', () => {
expect(guard([true])).toBe(false)
expect(guard([1, 'hello', true])).toBe(false)
})
})

describe('when passed a combination of guards', () => {
const guard = arrayOf([isBoolean, isNumber])

it('returns true when passed an array of matching types', () => {
expect(guard([false, 1])).toBe(true)
})

it('returns false when passed an array of non-matching types', () => {
expect(guard([1, false])).toBe(false)
expect(guard([false])).toBe(false)
expect(guard([false, 'hello'])).toBe(false)
})
})
})
24 changes: 21 additions & 3 deletions src/operator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { UnionToIntersection, Guard } from './utils'
import { Guard, UnionToIntersection } from './utils'

export function union<T extends any[]>(
...guards: { [K in keyof T]: (x: unknown) => x is T[K] }
Expand All @@ -16,13 +16,31 @@ export function intersection<T extends any[]>(
}
}

export function arrayOf<T extends unknown[]>(...guards: { [K in keyof T]: Guard<T[K]> }): Guard<T> {
export function arrayOf<T extends unknown[]>(guards: { [K in keyof T]: Guard<T[K]> }): Guard<T>
export function arrayOf<T extends unknown[]>(...guards: { [K in keyof T]: Guard<T[K]> }): Guard<T>
export function arrayOf<T extends unknown[]>(
...guards: { [K in keyof T]: Guard<T[K]> } | [{ [K in keyof T]: Guard<T[K]> }]
): Guard<T> {
const _guards = guards[0]
if (Array.isArray(_guards)) {
return (x: unknown): x is T => {
if (!Array.isArray(x) || x.length !== _guards.length) {
return false
}
return x.every((value, index) => _guards[index](value))
}
}

return function (x: unknown): x is T {
if (!Array.isArray(x)) {
return false
}

return x.every((item) => guards.some(guard => guard(item)))
return x.every((item) =>
guards.some((guard) => {
return (guard as any)(item)
})
)
}
}

Expand Down

0 comments on commit 507b763

Please sign in to comment.