Skip to content

Commit

Permalink
Add 'every' type predicate
Browse files Browse the repository at this point in the history
  • Loading branch information
Hugh Rawlinson authored and Hugh Rawlinson committed Jun 8, 2022
1 parent 1f0250b commit 1d89e04
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 0 deletions.
34 changes: 34 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,39 @@ if (isSuccess(message)) {
}
```

### `every()

Runtime array type validation. Checks each element of an array.

```ts
let arr: unknown[] = [1, 2, 3];
if (every(isNumber)(arr)) {
let typeCheck: number[] = arr;
}
```

Works with any narrowing validator, including schemas.

```ts
interface TestInterface {
id: number;
name: string;
}

const isTestInterface = schema<TestInterface>({
id: isNumber,
name: isString
});

let arr: unknown[] = [{ id: 1, name: 'aaa' }];

if (every(isTestInterface)(arr)) {
let typeCheck: TestInterface[] = arr;
}
```

```
## Version
- 1.1.0
Expand All @@ -247,3 +280,4 @@ if (isSuccess(message)) {
- 1.4.0
- replace ~~`isValidObject()`~~ with `schema()`
- add `literal()`
```
9 changes: 9 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,12 @@ export function schema<T>(schema: SchemaType<T>): Predicate<T> {
return false;
};
}

export function every<T>(predicate: Predicate<T>): Predicate<T[]> {
return function (value: unknown): value is T[] {
if (Array.isArray(value)) {
return value.every(predicate);
}
return false;
};
}
82 changes: 82 additions & 0 deletions test/every.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { schema, literal, every, isString, isNumber } from '../src/index';

test('fails when array contains elements of an unassignable type', () => {
expect(every(isString)([1, 2, 3])).toBe(false);
expect(every(isNumber)([1, '2', 3])).toBe(false);
});

test('passes when array contains correct type', () => {
expect(every(isNumber)([1, 2, 3])).toBe(true);
expect(every(isString)(['1', '2', '3'])).toBe(true);
});

test('passes when array is empty', () => {
expect(every(isString)([])).toBe(true);
expect(every(isNumber)([])).toBe(true);
});

interface TestInterface {
kind: 'test';
value: {
nestedString: string;
nestedNumber: number;
};
}

const isTestInterface = schema<TestInterface>({
kind: literal('test'),
value: schema<TestInterface['value']>({
nestedString: isString,
nestedNumber: isNumber
})
});

test('passes when array contains valid objects', () => {
expect(
every<TestInterface>(isTestInterface)([
{
kind: 'test',
value: {
nestedString: 'string',
nestedNumber: 1
}
}
])
).toBe(true);
});

test('fails when array contains invalid objects', () => {
expect(
every<TestInterface>(isTestInterface)([
{
kind: 'test',
value: {
nested_string: 'string'
}
}
])
).toBe(false);
});

every<string>(isString);

let arr: unknown[] = [1, 2, 3];
if (every(isNumber)(arr)) {
let typeCheck: number[] = arr;
}

interface TestInterfaceT {
id: number;
name: string;
}

const isTestInterfaceT = schema<TestInterfaceT>({
id: isNumber,
name: isString
});

let arr2: unknown[] = [{ id: 1, name: 'aaa' }];

if (every(isTestInterfaceT)(arr2)) {
let typeCheck: TestInterfaceT[] = arr2;
}

0 comments on commit 1d89e04

Please # to comment.