Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
"devDependencies": {
"@commitlint/config-conventional": "^19.7.1",
"@commitlint/types": "^19.5.0",
"@types/node": "^22.13.5",
"@types/node": "^22.13.8",
"@vitest/coverage-v8": "^3.0.7",
"@webdeveric/eslint-config-ts": "^0.11.0",
"@webdeveric/prettier-config": "^0.3.0",
Expand All @@ -96,7 +96,7 @@
"conventional-changelog-conventionalcommits": "^8.0.0",
"cspell": "^8.17.5",
"eslint": "^8.57.1",
"eslint-config-prettier": "^10.0.1",
"eslint-config-prettier": "^10.0.2",
"eslint-import-resolver-typescript": "^3.8.3",
"eslint-plugin-import": "^2.31.0",
"husky": "^9.1.7",
Expand All @@ -105,7 +105,7 @@
"prettier": "^3.5.2",
"rimraf": "^6.0.1",
"semantic-release": "^24.2.3",
"typescript": "^5.7.3",
"typescript": "^5.8.2",
"validate-package-exports": "^0.8.0",
"vitest": "^3.0.7"
}
Expand Down
442 changes: 221 additions & 221 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions src/predicate-factory/allOf.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import type { InferPredicatesReturnType, TypePredicateFn } from '../types/functions.js';
import type { UnionToIntersection } from '../types/utils.js';
import type { IntersectionOf } from '../types/utils.js';

/**
* All predicates must pass
*/
export const allOf = <Predicates extends TypePredicateFn<unknown>[]>(
...predicates: Predicates
): TypePredicateFn<UnionToIntersection<InferPredicatesReturnType<Predicates>>> => {
): TypePredicateFn<IntersectionOf<InferPredicatesReturnType<Predicates>>> => {
if (!predicates.length) {
throw new Error('Predicate functions not provided');
}

return (input: unknown): input is UnionToIntersection<InferPredicatesReturnType<Predicates>> =>
return (input: unknown): input is IntersectionOf<InferPredicatesReturnType<Predicates>> =>
predicates.every((predicate) => predicate(input));
};
5 changes: 3 additions & 2 deletions src/predicate-factory/anyOf.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import type { InferPredicatesReturnType, TypePredicateFn } from '../types/functions.js';
import type { UnionOf } from '../types/utils.js';

/**
* Any predicate can pass
*/
export const anyOf = <Predicates extends TypePredicateFn<unknown>[]>(
...predicates: Predicates
): TypePredicateFn<InferPredicatesReturnType<Predicates>> => {
): TypePredicateFn<UnionOf<InferPredicatesReturnType<Predicates>>> => {
if (!predicates.length) {
throw new Error('Predicate functions not provided');
}

return (input: unknown): input is InferPredicatesReturnType<Predicates> =>
return (input: unknown): input is UnionOf<InferPredicatesReturnType<Predicates>> =>
predicates.some((predicate) => predicate(input));
};
2 changes: 1 addition & 1 deletion src/types/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export type InferPredicateReturnType<Fn> = Fn extends TypePredicateFn<infer T> ?

export type InferPredicatesReturnType<Predicates extends TypePredicateFn<unknown>[]> = {
[K in keyof Predicates]: InferPredicateReturnType<Predicates[K]>;
}[number];
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type TypeAssertionFn<T> = (input: unknown, ...args: any[]) => asserts input is T;
Expand Down
10 changes: 9 additions & 1 deletion src/types/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ export type RequiredKeys<Type, Keys extends keyof Type> = Type extends any
? Omit<Type, Keys> & Required<Pick<Type, Keys>>
: never;

export type NonVoid<Type> = Type extends void ? never : Type;
export type NonVoid<Type> = Exclude<Type, void>;

export type Defined<Type> = Exclude<Type, undefined | void>;

export type RemoveNever<Type> = {
[Key in keyof Type as [Type[Key]] extends [never] ? never : Key]: Type[Key];
Expand Down Expand Up @@ -114,6 +116,12 @@ export type UnionToIntersection<Union> = (Union extends any ? (union: Union) =>
? Type
: never;

export type IntersectionOf<T extends unknown[]> = T extends [infer First, ...infer Rest]
? First & IntersectionOf<Rest>
: unknown;

export type UnionOf<T extends unknown[]> = T extends [infer First, ...infer Rest] ? First | UnionOf<Rest> : never;

export type Pretty<Type> = {
[Property in keyof Type]: Type[Property];
} & unknown;
14 changes: 7 additions & 7 deletions test/predicate-factory/allOf.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { describe, it, expect } from 'vitest';

import { isNumber } from '../../src/predicate/isNumber.js';
import { isObjectWith } from '../../src/predicate/isObjectWith.js';
import { isString } from '../../src/predicate/isString.js';
import { allOf } from '../../src/predicate-factory/allOf.js';
import { createObjectShapePredicate } from '../../src/predicate-factory/createObjectShapePredicate.js';

describe('allOf()', () => {
it('Requires one or more type predicate function', () => {
Expand All @@ -12,12 +12,12 @@ describe('allOf()', () => {

it('Returns a type predicate function', () => {
const fn = allOf(
(input): input is { name: string } => {
return isObjectWith(input, 'name') && isString(input.name);
},
(input): input is { age: number } => {
return isObjectWith(input, 'age') && isNumber(input.age);
},
createObjectShapePredicate({
name: isString,
}),
createObjectShapePredicate({
age: isNumber,
}),
);

expect(fn).instanceOf(Function);
Expand Down
Loading