diff --git a/index.d.ts b/index.d.ts index 33213ef50..15542d3cc 100644 --- a/index.d.ts +++ b/index.d.ts @@ -156,6 +156,7 @@ export type {IfNull} from './source/if-null.d.ts'; export type {IsUndefined} from './source/is-undefined.d.ts'; export type {And} from './source/and.d.ts'; export type {Or} from './source/or.d.ts'; +export type {OrAll} from './source/or-all.d.ts'; export type {Xor} from './source/xor.d.ts'; export type {AllExtend, AllExtendOptions} from './source/all-extend.d.ts'; export type {SomeExtend, SomeExtendOptions} from './source/some-extend.d.ts'; diff --git a/readme.md b/readme.md index 4549012a1..8a6e6ef9f 100644 --- a/readme.md +++ b/readme.md @@ -180,9 +180,10 @@ Click the type names for complete docs. - [`AllUnionFields`](source/all-union-fields.d.ts) - Create a type with all fields from a union of object types. - [`DistributedOmit`](source/distributed-omit.d.ts) - Omits keys from a type, distributing the operation over a union. - [`DistributedPick`](source/distributed-pick.d.ts) - Picks keys from a type, distributing the operation over a union. -- [`And`](source/and.d.ts) - Returns a boolean for whether two given types are both true. -- [`Or`](source/or.d.ts) - Returns a boolean for whether either of two given types is true. -- [`Xor`](source/xor.d.ts) - Returns a boolean for whether only one of two given types is true. +- [`And`](source/and.d.ts) - Returns a boolean for whether two given types are both `true`. +- [`Or`](source/or.d.ts) - Returns a boolean for whether either of two given types is `true`. +- [`Xor`](source/xor.d.ts) - Returns a boolean for whether only one of two given types is `true`. +- [`OrAll`](source/or-all.d.ts) - Returns a boolean for whether any of the given elements is `true`. - [`AllExtend`](source/all-extend.d.ts) - Returns a boolean for whether every element in an array type extends another type. - [`SomeExtend`](source/some-extend.d.ts) - Returns a boolean for whether some element in an array type extends another type. - [`NonEmptyTuple`](source/non-empty-tuple.d.ts) - Matches any non-empty tuple. diff --git a/source/or-all.d.ts b/source/or-all.d.ts new file mode 100644 index 000000000..d39b2f316 --- /dev/null +++ b/source/or-all.d.ts @@ -0,0 +1,72 @@ +import type {SomeExtend} from './some-extend.d.ts'; + +/** +Returns a boolean for whether any of the given elements is `true`. + +Use-cases: +- Check if at least one condition in a list of booleans is met. + +@example +``` +import type {OrAll} from 'type-fest'; + +type FFT = OrAll<[false, false, true]>; +//=> true + +type FFF = OrAll<[false, false, false]>; +//=> false +``` + +Note: When `boolean` is passed as an element, it is distributed into separate cases, and the final result is a union of those cases. +For example, `OrAll<[false, boolean]>` expands to `OrAll<[false, true]> | OrAll<[false, false]>`, which simplifies to `true | false` (i.e., `boolean`). + +@example +``` +import type {OrAll} from 'type-fest'; + +type A = OrAll<[false, boolean]>; +//=> boolean + +type B = OrAll<[true, boolean]>; +//=> true +``` + +Note: If `never` is passed as an element, it is treated as `false` and the result is computed accordingly. + +@example +``` +import type {OrAll} from 'type-fest'; + +type A = OrAll<[never, never, true]>; +//=> true + +type B = OrAll<[never, never, false]>; +//=> false + +type C = OrAll<[never, never, never]>; +//=> false + +type D = OrAll<[never, never, boolean]>; +//=> boolean +``` + +Note: If `any` is passed as an element, it is treated as `boolean` and the result is computed accordingly. + +@example +``` +import type {OrAll} from 'type-fest'; + +type A = OrAll<[false, any]>; +//=> boolean + +type B = OrAll<[true, any]>; +//=> true +``` + +Note: `OrAll<[]>` evaluates to `false` because there are no `true` elements in an empty tuple. See [Wikipedia: Clause (logic) > Empty clauses](https://en.wikipedia.org/wiki/Clause_(logic)#Empty_clauses:~:text=The%20truth%20evaluation%20of%20an%20empty%20disjunctive%20clause%20is%20always%20false.). + +@see {@link Or} +*/ +export type OrAll = SomeExtend; + +export {}; diff --git a/source/or.d.ts b/source/or.d.ts index ca2bc0a68..46a164314 100644 --- a/source/or.d.ts +++ b/source/or.d.ts @@ -1,5 +1,4 @@ -import type {If} from './if.d.ts'; -import type {IsNever} from './is-never.d.ts'; +import type {OrAll} from './or-all.d.ts'; /** Returns a boolean for whether either of two given types is true. @@ -74,16 +73,10 @@ type G = Or; //=> false ``` +@see {@link OrAll} @see {@link And} @see {@link Xor} */ -export type Or = - _Or, false, A>, If, false, B>>; // `never` is treated as `false` - -export type _Or = A extends true - ? true - : B extends true - ? true - : false; +export type Or = OrAll<[A, B]>; export {}; diff --git a/test-d/or-all.ts b/test-d/or-all.ts new file mode 100644 index 000000000..216e97ad3 --- /dev/null +++ b/test-d/or-all.ts @@ -0,0 +1,62 @@ +import {expectType} from 'tsd'; +import type {OrAll} from '../source/or-all.d.ts'; + +declare const boolean: boolean; + +// Basic boolean combinations +expectType>(true); +expectType>(true); +expectType>(true); +expectType>(false); + +// Multiple elements in a tuple +expectType>(true); +expectType>(false); + +// `boolean` element +expectType>(boolean); +expectType>(true); +expectType>(boolean); + +// Unions +expectType>(boolean); // `true` | `false` +expectType>(true); // `true` | `true` +expectType>(false); // `false` | `false` +expectType>(boolean); // `true` | `boolean` +expectType>(boolean); // `false` | `boolean` +expectType>(boolean); // `boolean` | `boolean` + +// Tuples with rest element +expectType]>>(false); +expectType, true]>>(true); +expectType, boolean]>>(boolean); + +// Non-tuple arrays +expectType>>(true); +expectType>>(false); +expectType>(boolean); + +// Readonly arrays +expectType>(true); +expectType>(false); +expectType>(boolean); +expectType>>(true); +expectType>>(false); +expectType>(boolean); + +// Boundary cases +expectType>(false); + +expectType>(boolean); +expectType>(true); +expectType>(boolean); + +expectType>(false); +expectType>(true); +expectType>(false); + +// Errors with non-boolean or optional elements +// @ts-expect-error +type Error1 = OrAll<[1, 0]>; +// @ts-expect-error +type Error2 = OrAll<[true, false?]>;