inferred-types 0.33.4 → 0.34.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/.vscode/settings.json +1 -0
  2. package/dist/index.d.ts +204 -103
  3. package/dist/index.js +20 -6
  4. package/dist/index.mjs +17 -6
  5. package/package.json +3 -3
  6. package/src/runtime/combinators/or.ts +4 -14
  7. package/src/runtime/type-checks/isArray.ts +30 -1
  8. package/src/runtime/type-checks/isBoolean.ts +1 -1
  9. package/src/runtime/type-checks/isFalse.ts +24 -12
  10. package/src/runtime/type-checks/isObject.ts +1 -1
  11. package/src/runtime/type-checks/isString.ts +1 -1
  12. package/src/runtime/type-checks/isTrue.ts +13 -29
  13. package/src/runtime/type-checks/isUndefined.ts +1 -1
  14. package/src/runtime/type-checks/startsWith.ts +9 -11
  15. package/src/types/Mutable.ts +1 -1
  16. package/src/types/Narrowable.ts +1 -2
  17. package/src/types/boolean-logic/EndsWith.ts +40 -0
  18. package/src/types/boolean-logic/Extends.ts +22 -0
  19. package/src/types/{type-checks → boolean-logic}/Includes.ts +3 -4
  20. package/src/types/{type-checks → boolean-logic}/IsLiteral.ts +52 -5
  21. package/src/types/boolean-logic/IsScalar.ts +20 -0
  22. package/src/types/{type-checks → boolean-logic}/IsUndefined.ts +5 -1
  23. package/src/types/boolean-logic/Or.ts +12 -0
  24. package/src/types/{type-checks → boolean-logic}/StartsWith.ts +12 -13
  25. package/src/types/{type-checks → boolean-logic}/TypeDefault.ts +1 -1
  26. package/src/types/boolean-logic/array.ts +57 -0
  27. package/src/types/boolean-logic/boolean.ts +84 -0
  28. package/src/types/boolean-logic/equivalency.ts +15 -0
  29. package/src/types/{type-checks → boolean-logic}/index.ts +4 -3
  30. package/src/types/{type-checks → boolean-logic}/object.ts +4 -1
  31. package/src/types/{type-checks → boolean-logic}/string.ts +1 -1
  32. package/src/types/dictionary/MapTo.ts +1 -1
  33. package/src/types/functions/LogicFunction.ts +1 -1
  34. package/src/types/index.ts +1 -1
  35. package/src/types/lists/FilterTuple.ts +20 -0
  36. package/src/types/lists/index.ts +1 -0
  37. package/tests/boolean-logic/Contains.test.ts +55 -0
  38. package/tests/{TypeInfo → boolean-logic}/IsLiteral.spec.ts +0 -0
  39. package/tests/dictionary/{PrependValuesWithFunction.ts → PrependValuesWithFunction.test.ts} +0 -0
  40. package/tests/dictionary/TypeDefault.test.ts +1 -1
  41. package/tests/lists/Length.test.ts +19 -0
  42. package/tests/runtime/if-is.spec.ts +113 -5
  43. package/src/types/type-checks/EndsWith.ts +0 -22
  44. package/src/types/type-checks/Extends.ts +0 -14
  45. package/src/types/type-checks/IsBooleanLiteral.ts +0 -16
  46. package/src/types/type-checks/IsNumericLiteral.ts +0 -16
  47. package/src/types/type-checks/IsScalar.ts +0 -14
  48. package/src/types/type-checks/IsStringLiteral.ts +0 -14
@@ -1,15 +1,5 @@
1
- import { LogicFunction } from "src/types/functions";
1
+ import { Or } from "src/types/boolean-logic/Or";
2
2
 
3
- /**
4
- * Groups a number of "logic functions" together by combining their results using
5
- * the logical **OR** operator.
6
- *
7
- * **Note:** a "logic function" is any function which returns a boolean
8
- */
9
- export const or = <T extends any[]>(...ops: LogicFunction<T>[]): LogicFunction<T> => {
10
- const fn: LogicFunction<T> = (...args: T) => {
11
- return [...ops].some((i) => i(...args));
12
- };
13
-
14
- return fn;
15
- };
3
+ export function or<O extends readonly boolean[]>(...conditions: O) {
4
+ return (conditions.some((v) => v === true) ? true : false) as Or<O>;
5
+ }
@@ -1,5 +1,34 @@
1
- export type IsArray<T> = T extends any[] ? true : false;
1
+ import { IsArray, IfArray } from "src/types/boolean-logic/array";
2
+ import { Narrowable } from "src/types/Narrowable";
2
3
 
3
4
  export function isArray<T>(i: T) {
4
5
  return (Array.isArray(i) === true) as IsArray<T>;
5
6
  }
7
+
8
+ /**
9
+ * **ifArray**(T, IF, ELSE)
10
+ *
11
+ * A utility which evaluates a type `T` for whether it is an array and then
12
+ */
13
+ export function ifArray<
14
+ // value which is possibly an array
15
+ T extends Narrowable,
16
+ // functions which return a known type
17
+ IF extends Narrowable,
18
+ ELSE extends Narrowable
19
+ >(
20
+ val: T,
21
+ isAnArray: <N extends T & readonly any[]>(arr: N) => IF,
22
+ isNotAnArray: <N extends Exclude<T, any[]>>(nonArr: N) => ELSE
23
+ ) {
24
+ return (isArray(val) ? isAnArray(val as any) : isNotAnArray(val as any)) as IfArray<T, IF, ELSE>;
25
+ }
26
+
27
+ export function ifArrayPartial<T extends Narrowable>() {
28
+ return <IF extends Narrowable, ELSE extends Narrowable>(
29
+ isAnArray: <N extends T & readonly any[]>(arr: N) => IF,
30
+ isNotAnArray: <N extends Exclude<T, any[]>>(nonArr: N) => ELSE
31
+ ) => {
32
+ return <V extends T>(val: V) => ifArray(val, isAnArray, isNotAnArray);
33
+ };
34
+ }
@@ -1,4 +1,4 @@
1
- export type IsBoolean<T> = T extends boolean ? true : false;
1
+ import { IsBoolean } from "src/types/boolean-logic";
2
2
 
3
3
  /**
4
4
  * Runtime and type checks whether a variable is a boolean value.
@@ -1,17 +1,29 @@
1
+ import { IfFalse, IsFalse } from "src/types/boolean-logic/boolean";
1
2
  import { Narrowable } from "src/types/Narrowable";
2
- import { IsBoolean } from "./isBoolean";
3
-
4
- export type IsFalse<T extends Narrowable> = IsBoolean<T> extends true
5
- ? // is a boolean
6
- T extends false
7
- ? true
8
- : true extends T
9
- ? false
10
- : // is of boolean type; therefore narrow type is unknown
11
- unknown
12
- : // not a boolean
13
- false;
14
3
 
15
4
  export function isFalse<T>(i: T) {
16
5
  return (typeof i === "boolean" && !i) as IsFalse<T>;
17
6
  }
7
+
8
+ /**
9
+ * **ifTrue**
10
+ *
11
+ * Strongly type-aware conditional statement which checks whether a value is
12
+ * a _true_ and returns one of two values (strongly typed) based on the evaluation
13
+ * of this criteria.
14
+ *
15
+ * @param val the value being tested
16
+ * @param ifVal the value (strongly typed) returned if val is _true_ value
17
+ * @param elseVal the value (strongly typed) returned if val is NOT a _true_ value
18
+ *
19
+ * Note: at runtime there's no way to distinguish if the value was widely or loosely
20
+ * typed so unlike the type utility there is no "MAYBE" state but if a wide type if
21
+ * encountered the _type_ will the union of `IF` and `ELSE`.
22
+ */
23
+ export function ifFalse<T extends boolean, IF extends Narrowable, ELSE extends Narrowable>(
24
+ val: T,
25
+ ifVal: IF,
26
+ elseVal: ELSE
27
+ ) {
28
+ return (isFalse(val) ? ifVal : elseVal) as IfFalse<T, IF, ELSE, IF | ELSE>;
29
+ }
@@ -1,5 +1,5 @@
1
1
  import { FunctionType, Narrowable, Not } from "src/types";
2
- import { IsObject } from "src/types/type-checks";
2
+ import { IsObject } from "src/types/boolean-logic";
3
3
 
4
4
  export type ObjectType = Not<Record<string, Narrowable>, FunctionType>;
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { Narrowable } from "src/types/Narrowable";
2
- import { IfString, IsString } from "src/types/type-checks/string";
2
+ import { IfString, IsString } from "src/types/boolean-logic/string";
3
3
 
4
4
  /**
5
5
  * **isString**
@@ -1,28 +1,5 @@
1
- import { Narrowable } from "src/types";
2
- import type { IsBoolean } from "./isBoolean";
3
-
4
- /**
5
- * Type utility which returns `true` or `false` based on
6
- * whether the type holds the narrow "true" type.
7
- * ```ts
8
- * // true
9
- * type T = IsTrue<true>;
10
- * // unknown
11
- * type U = IsTrue<boolean>;
12
- * // false
13
- * type F = IsTrue<false>;
14
- * type F2 = IsTrue<"false">;
15
- * ```
16
- */
17
- export type IsTrue<T> = IsBoolean<T> extends true
18
- ? // is a boolean
19
- T extends true
20
- ? true
21
- : T extends false
22
- ? false
23
- : unknown
24
- : // not a boolean
25
- false;
1
+ import { IfTrue, IsTrue } from "src/types/boolean-logic";
2
+ import { Narrowable } from "src/types/Narrowable";
26
3
 
27
4
  /**
28
5
  * Run-time and type checking of whether a variable is `true`.
@@ -35,13 +12,20 @@ export function isTrue<T extends Narrowable>(i: T) {
35
12
  * **ifTrue**
36
13
  *
37
14
  * Strongly type-aware conditional statement which checks whether a value is
38
- * a _true_ and returns one of two values (strongly typed) based on the evaluation
39
- * of this criteria.
15
+ * _true_.
40
16
  *
41
17
  * @param val the value being tested
42
18
  * @param ifVal the value (strongly typed) returned if val is _true_ value
43
19
  * @param elseVal the value (strongly typed) returned if val is NOT a _true_ value
20
+ *
21
+ * Note: at runtime there's no way to distinguish if the value was widely or loosely
22
+ * typed so unlike the type utility there is no "MAYBE" state but if a wide type if
23
+ * encountered the _type_ will the union of `IF` and `ELSE`.
44
24
  */
45
- export function ifTrue<T extends Narrowable, IF, ELSE>(val: T, ifVal: IF, elseVal: ELSE) {
46
- return (isTrue(val) ? ifVal : elseVal) as IsTrue<T> extends true ? IF : ELSE;
25
+ export function ifTrue<T extends boolean, IF extends Narrowable, ELSE extends Narrowable>(
26
+ val: T,
27
+ ifVal: IF,
28
+ elseVal: ELSE
29
+ ) {
30
+ return (isTrue(val) ? ifVal : elseVal) as IfTrue<T, IF, ELSE, IF | ELSE>;
47
31
  }
@@ -1,5 +1,5 @@
1
1
  import { Narrowable } from "src/types";
2
- import { IsUndefined } from "src/types/type-checks/IsUndefined";
2
+ import { IsUndefined } from "src/types/boolean-logic/IsUndefined";
3
3
 
4
4
  export function isUndefined<T extends Narrowable>(i: T) {
5
5
  return (typeof i === "undefined") as undefined extends T ? true : false;
@@ -1,5 +1,6 @@
1
- import { IfStartsWith, StartsWith } from "src/types/type-checks";
2
- import { IfUndefined } from "src/types/type-checks/IsUndefined";
1
+ import { Narrowable } from "src/types";
2
+ import { IfStartsWith, StartsWith } from "src/types/boolean-logic";
3
+ import { IfUndefined } from "src/types/boolean-logic/IsUndefined";
3
4
  import { createFnWithProps } from "../createFnWithProps";
4
5
  import { box, Box } from "../literals";
5
6
  import { ifTrue } from "./isTrue";
@@ -88,22 +89,19 @@ export type StringLiteralFn<S extends string = string> = <T extends S>(input: T)
88
89
  * returns is able to
89
90
  */
90
91
  export const ifStartsWith =
91
- <
92
- TStartsWith extends string,
93
- TIf extends <T extends string>(input: T) => any,
94
- TElse extends <T extends string>(input: T) => any
95
- >(
92
+ <TStartsWith extends string, TIf extends Narrowable, TElse extends Narrowable>(
96
93
  /** the string literal _start value_ which a string must begin with */
97
94
  start: TStartsWith,
98
95
  /** a mutation function when a value _does_ start with `TStartsWith` */
99
- isTrue: TIf,
96
+ isTrue: <T extends string>(input: T) => TIf,
100
97
  /** an optional mutation function */
101
- isFalse: TElse
98
+ isFalse: <T extends string>(input: T) => TElse
102
99
  ) =>
103
- <I extends string>(input: I) =>
100
+ <TTextValue extends string>(input: TTextValue) =>
104
101
  ifTrue(
105
102
  // condition
106
103
  startsWith(start)(input),
104
+ // handlers
107
105
  isTrue(input),
108
106
  isFalse(input)
109
- ) as IfStartsWith<I, TStartsWith, ReturnType<TIf>, ReturnType<TElse>>;
107
+ );
@@ -1,4 +1,4 @@
1
- import { IsObject } from "./type-checks";
1
+ import { IsObject } from "./boolean-logic";
2
2
 
3
3
  /**
4
4
  * Makes a readonly structure mutable
@@ -2,5 +2,4 @@
2
2
  * A union of types used in conjunction with the `literalValues()` function
3
3
  * to produce a _narrow_ type definition of a passed in dictionary object.
4
4
  */
5
- export type Narrowable =
6
- string | number | boolean | symbol | object | undefined | void | null | {};
5
+ export type Narrowable = string | number | boolean | symbol | object | undefined | void | null | {};
@@ -0,0 +1,40 @@
1
+ import { IsStringLiteral } from "src/types/boolean-logic";
2
+ import { Narrowable } from "../Narrowable";
3
+
4
+ /**
5
+ * **EndsWith**<T,U>
6
+ *
7
+ * A type utility which checks whether `T` _ends with_ the string literal `U`.
8
+ *
9
+ * If both `T` and `U` are string literals then the type system will resolve
10
+ * to a literal `true` or `false` but if either is not a literal that it will
11
+ * just resolve to `boolean` as the value can not be known at design time..
12
+ */
13
+ export type EndsWith<
14
+ TValue extends string,
15
+ TEndsWith extends string
16
+ > = IsStringLiteral<TEndsWith> extends true
17
+ ? IsStringLiteral<TValue> extends true // both literals
18
+ ? TValue extends `${string}${TEndsWith}`
19
+ ? true
20
+ : false
21
+ : boolean
22
+ : boolean;
23
+
24
+ /**
25
+ * **IfEndsWith**<TValue, TEndsWith, IF, ELSE, MAYBE>
26
+ *
27
+ * Type utility which converts type to `IF` type _if_ `TValue` _ends with_ `TEndsWith` but
28
+ * otherwise converts type to `ELSE`. If there are wide types in the mix then the type will
29
+ * result in the union of IF and ELSE.
30
+ */
31
+ export type IfEndsWith<
32
+ TValue extends string,
33
+ TEndsWith extends string,
34
+ IF extends Narrowable,
35
+ ELSE extends Narrowable
36
+ > = EndsWith<TValue, TEndsWith> extends true
37
+ ? IF
38
+ : EndsWith<TValue, TEndsWith> extends false
39
+ ? ELSE
40
+ : IF | ELSE;
@@ -0,0 +1,22 @@
1
+ import { Narrowable } from "../Narrowable";
2
+
3
+ /**
4
+ * **Extends**`<T, EXTENDS>`
5
+ *
6
+ * Boolean type utility which returns `true` if `T` _extends_ `EXTENDS`.
7
+ */
8
+ export type Extends<T extends Narrowable, EXTENDS extends Narrowable> = T extends EXTENDS
9
+ ? true
10
+ : false;
11
+ /**
12
+ * **IfExtends**
13
+ *
14
+ * Branching type utility which returns type `IF` when `E` _extends_ `T`; otherwise
15
+ * it will return the type `ELSE`.
16
+ */
17
+ export type IfExtends<
18
+ T extends Narrowable,
19
+ EXTENDS extends Narrowable,
20
+ IF extends Narrowable,
21
+ ELSE extends Narrowable
22
+ > = Extends<T, EXTENDS> extends true ? IF : ELSE;
@@ -1,9 +1,8 @@
1
1
  import { TupleToUnion } from "../type-conversion";
2
- import { IsLiteral } from "./IsLiteral";
3
- import { IsStringLiteral } from "./IsStringLiteral";
2
+ import { IsLiteral, IsStringLiteral } from "./IsLiteral";
4
3
 
5
4
  /**
6
- * **Includes<TSource, TValue>**
5
+ * **Includes**`<TSource, TValue>`
7
6
  *
8
7
  * Type utility which returns `true` or `false` based on whether `TValue` is found
9
8
  * in `TSource`. Where `TSource` can be a string literal or an array of string literals.
@@ -13,7 +12,7 @@ import { IsStringLiteral } from "./IsStringLiteral";
13
12
  * a type of `boolean`.
14
13
  */
15
14
  export type Includes<
16
- TSource extends string | string[],
15
+ TSource extends string | readonly string[],
17
16
  TValue extends string
18
17
  > = TSource extends string[]
19
18
  ? IsStringLiteral<TupleToUnion<TSource>> extends true
@@ -1,6 +1,47 @@
1
- import { IsBooleanLiteral } from "./IsBooleanLiteral";
2
- import { IsStringLiteral } from "./IsStringLiteral";
3
- import { IsNumericLiteral } from "./IsNumericLiteral";
1
+ import { Narrowable } from "../Narrowable";
2
+ import { IsBooleanLiteral } from "./boolean";
3
+
4
+ /**
5
+ * **IsStringLiteral**
6
+ *
7
+ * Type utility which returns true/false if the string a _string literal_ versus
8
+ * just the _string_ type.
9
+ */
10
+ export type IsStringLiteral<T extends Narrowable> = [T] extends [string]
11
+ ? string extends T
12
+ ? false
13
+ : true
14
+ : false;
15
+
16
+ /**
17
+ * **IfStringLiteral**
18
+ *
19
+ * Branch utility which returns `IF` type when `T` is a string literal and `ELSE` otherwise
20
+ */
21
+ export type IfStringLiteral<T extends string, IF extends Narrowable, ELSE extends Narrowable> = [
22
+ IsStringLiteral<T>
23
+ ] extends [true]
24
+ ? IF
25
+ : ELSE;
26
+
27
+ /**
28
+ * **IsNumericLiteral**
29
+ *
30
+ * Type utility which returns true/false if the numeric value a _numeric literal_ versus
31
+ * just the _number_ type.
32
+ */
33
+ export type IsNumericLiteral<T extends number> = number extends T ? false : true;
34
+
35
+ /**
36
+ * **IfNumericLiteral**
37
+ *
38
+ * Branch utility which returns `IF` type when `T` is a numeric literal and `ELSE` otherwise
39
+ */
40
+ export type IfNumericLiteral<
41
+ T extends number,
42
+ IF extends Narrowable,
43
+ ELSE extends Narrowable
44
+ > = IsNumericLiteral<T> extends true ? IF : ELSE;
4
45
 
5
46
  // [note on handling of boolean](https://stackoverflow.com/questions/74213646/detecting-type-literals-works-in-isolation-but-not-when-combined-with-other-lite/74213713#74213713)
6
47
 
@@ -43,7 +84,9 @@ export type IsOptionalLiteral<T> = [Exclude<T, undefined>] extends [string]
43
84
  *
44
85
  * Branch type utility with return `IF` when `T` is a _literal_ value and `ELSE` otherwise
45
86
  */
46
- export type IfLiteral<T, IF, ELSE> = IsLiteral<T> extends true ? IF : ELSE;
87
+ export type IfLiteral<T, IF extends Narrowable, ELSE extends Narrowable> = IsLiteral<T> extends true
88
+ ? IF
89
+ : ELSE;
47
90
 
48
91
  /**
49
92
  * **IfOptionalLiteral**
@@ -51,4 +94,8 @@ export type IfLiteral<T, IF, ELSE> = IsLiteral<T> extends true ? IF : ELSE;
51
94
  * Branch type utility with return `IF` when `T` is a _literal_ value (with possibly
52
95
  * the inclusion of _undefined_); otherwise returns the type `ELSE`
53
96
  */
54
- export type IfOptionalLiteral<T, IF, ELSE> = IsOptionalLiteral<T> extends true ? IF : ELSE;
97
+ export type IfOptionalLiteral<
98
+ T,
99
+ IF extends Narrowable,
100
+ ELSE extends Narrowable
101
+ > = IsOptionalLiteral<T> extends true ? IF : ELSE;
@@ -0,0 +1,20 @@
1
+ import { Narrowable } from "../Narrowable";
2
+
3
+ export type IsScalar<T extends Narrowable> = [T] extends [string]
4
+ ? true
5
+ : [T] extends [number]
6
+ ? true
7
+ : [T] extends [boolean]
8
+ ? true
9
+ : false;
10
+
11
+ /**
12
+ * **IfScalar**`<T, IF, ELSE>`
13
+ *
14
+ * Branch type utility which returns `IF` when `T` is a scalar value (aka, string, number, or boolean) and `ELSE` otherwise
15
+ */
16
+ export type IfScalar<
17
+ T extends Narrowable,
18
+ IF extends Narrowable,
19
+ ELSE extends Narrowable
20
+ > = IsScalar<T> extends true ? IF : ELSE;
@@ -13,4 +13,8 @@ export type IsUndefined<T extends Narrowable> = T extends undefined ? true : fal
13
13
  * Type utility which returns `IF` type when `T` is an _undefined_
14
14
  * otherwise returns `ELSE` type.
15
15
  */
16
- export type IfUndefined<T, IF, ELSE> = IsUndefined<T> extends true ? IF : ELSE;
16
+ export type IfUndefined<
17
+ T,
18
+ IF extends Narrowable,
19
+ ELSE extends Narrowable
20
+ > = IsUndefined<T> extends true ? IF : ELSE;
@@ -0,0 +1,12 @@
1
+ import { NarrowlyContains } from "./array";
2
+
3
+ /**
4
+ * **Or**`<T>`
5
+ *
6
+ * Takes an array of boolean values and produces a boolean OR across these values
7
+ */
8
+ export type Or<T extends readonly boolean[]> = NarrowlyContains<true, T> extends true
9
+ ? true
10
+ : NarrowlyContains<boolean, T> extends true
11
+ ? boolean
12
+ : false;
@@ -1,4 +1,4 @@
1
- import { IfStringLiteral } from "src/types/type-checks";
1
+ import { IsStringLiteral } from "src/types/boolean-logic";
2
2
  import { Narrowable } from "../Narrowable";
3
3
  /**
4
4
  * **StartsWith**<TValue, TStartsWith>
@@ -9,17 +9,16 @@ import { Narrowable } from "../Narrowable";
9
9
  * to a literal `true` or `false` but if either is not a literal that it will
10
10
  * just resolve to `boolean` as the value can not be known at design time..
11
11
  */
12
- export type StartsWith<TValue extends unknown, TStartsWith extends unknown> = TValue extends string
13
- ? TStartsWith extends string
12
+ export type StartsWith<
13
+ TValue extends string,
14
+ TStartsWith extends string
15
+ > = IsStringLiteral<TStartsWith> extends true
16
+ ? IsStringLiteral<TValue> extends true // both literals
14
17
  ? TValue extends `${TStartsWith}${string}`
15
- ? IfStringLiteral<
16
- TValue, //
17
- IfStringLiteral<TStartsWith, true, boolean>,
18
- boolean
19
- >
20
- : IfStringLiteral<TValue, false, boolean>
21
- : false
22
- : false;
18
+ ? true
19
+ : false
20
+ : boolean
21
+ : boolean;
23
22
 
24
23
  /**
25
24
  * **IfStartsWith**<TValue, TStartsWith, IF, ELSE, MAYBE>
@@ -32,8 +31,8 @@ export type StartsWith<TValue extends unknown, TStartsWith extends unknown> = TV
32
31
  * type and therefore the type is unknown at design time.
33
32
  */
34
33
  export type IfStartsWith<
35
- TValue extends unknown,
36
- TStartsWith extends unknown,
34
+ TValue extends string,
35
+ TStartsWith extends string,
37
36
  IF extends Narrowable,
38
37
  ELSE extends Narrowable
39
38
  > = StartsWith<TValue, TStartsWith> extends true
@@ -1,4 +1,4 @@
1
- import { IsObject } from "src/types/type-checks";
1
+ import { IsObject } from "src/types/boolean-logic";
2
2
  import { SimplifyObject } from "../SimplifyObject";
3
3
  import { IfExtends } from "./Extends";
4
4
  import { IfOptionalLiteral } from "./IsLiteral";
@@ -0,0 +1,57 @@
1
+ import { Equal } from "./equivalency";
2
+ import { AfterFirst, First } from "../lists";
3
+ import { Narrowable } from "../Narrowable";
4
+
5
+ export type IsArray<T> = [T] extends [any[]] ? true : [T] extends [readonly any[]] ? true : false;
6
+ export type IsReadonlyArray<T> = T extends readonly any[] ? true : false;
7
+
8
+ /**
9
+ * **IfArray**`<T, IF, ELSE>`
10
+ *
11
+ * Type utility which convert to type `IF` or `ELSE` based on whether `T` is an array
12
+ */
13
+ export type IfArray<
14
+ T extends Narrowable,
15
+ IF extends Narrowable,
16
+ ELSE extends Narrowable
17
+ > = IsArray<T> extends true ? IF : ELSE;
18
+
19
+ /**
20
+ * **IfArray**`<T, IF, ELSE>`
21
+ *
22
+ * Type utility which convert to type `IF` or `ELSE` based on whether `T` is a readonly array
23
+ */
24
+ export type IfReadonlyArray<
25
+ T extends Narrowable,
26
+ IF extends Narrowable,
27
+ ELSE extends Narrowable
28
+ > = IsReadonlyArray<T> extends true ? IF : ELSE;
29
+
30
+ /**
31
+ * **Contains**`<T, A>`
32
+ *
33
+ * Type utility which checks whether a type `T` exists within an array `A`. Result is
34
+ * `true` if `T` _extends_ any element in `A` making it match widely against `A`. If you
35
+ * prefer a narrower match you can use `NarrowlyContains<T,A>` instead.
36
+ */
37
+ export type Contains<T extends Narrowable, A extends readonly any[]> = First<A> extends T
38
+ ? true
39
+ : [] extends AfterFirst<A>
40
+ ? false
41
+ : Contains<T, AfterFirst<A>>;
42
+
43
+ /**
44
+ * **NarrowlyContains**`<T, A>`
45
+ *
46
+ * Type utility which checks whether a type `T` exists within an array `A`. Result is
47
+ * `true` if `T` _extends_ any element in `A` making it match widely against `A`. If you
48
+ * prefer a wider match you can use `Contains<T,A>` instead.
49
+ */
50
+ export type NarrowlyContains<T extends Narrowable, A extends readonly any[]> = Equal<
51
+ First<A>,
52
+ T
53
+ > extends true
54
+ ? true
55
+ : [] extends AfterFirst<A>
56
+ ? false
57
+ : NarrowlyContains<T, AfterFirst<A>>;
@@ -0,0 +1,84 @@
1
+ import { Narrowable } from "../Narrowable";
2
+
3
+ export type IsBoolean<T> = T extends boolean ? true : false;
4
+
5
+ /**
6
+ * Type utility which returns `true` or `false` based on
7
+ * whether the type holds the narrow "true" type.
8
+ * ```ts
9
+ * // true
10
+ * type T = IsTrue<true>;
11
+ * // boolean
12
+ * type U = IsTrue<boolean>;
13
+ * // false
14
+ * type F = IsTrue<false>;
15
+ * type F2 = IsTrue<"false">;
16
+ * ```
17
+ */
18
+ export type IsTrue<T extends Narrowable> = IsBoolean<T> extends true
19
+ ? // is a boolean
20
+ T extends true
21
+ ? true
22
+ : T extends false
23
+ ? false
24
+ : unknown
25
+ : // not a boolean
26
+ false;
27
+
28
+ export type IsFalse<T extends Narrowable> = IsBoolean<T> extends true
29
+ ? // is a boolean
30
+ T extends false
31
+ ? true
32
+ : true extends T
33
+ ? false
34
+ : // is of boolean type; therefore narrow type is unknown
35
+ unknown
36
+ : // not a boolean
37
+ false;
38
+
39
+ /**
40
+ * Type utility which checks for literal `true` value and then switches type
41
+ * to the IF, ELSE, or MAYBE generic types passed in where _maybe_ is when T
42
+ * is the wide type of `boolean`
43
+ */
44
+ export type IfTrue<
45
+ T extends boolean,
46
+ IF extends Narrowable,
47
+ ELSE extends Narrowable,
48
+ MAYBE extends Narrowable
49
+ > = IsTrue<T> extends true ? IF : IsTrue<T> extends false ? ELSE : MAYBE;
50
+
51
+ /**
52
+ * Type utility which checks for literal `false` value and then switches type
53
+ * to the IF, ELSE, or MAYBE generic types passed in where _maybe_ is when T
54
+ * is the wide type of `boolean`
55
+ */
56
+ export type IfFalse<
57
+ T extends Narrowable,
58
+ IF extends Narrowable,
59
+ ELSE extends Narrowable,
60
+ MAYBE extends Narrowable
61
+ > = IsFalse<T> extends true ? IF : IsTrue<T> extends false ? ELSE : MAYBE;
62
+
63
+ /**
64
+ * **IsBooleanLiteral**
65
+ *
66
+ * Type utility which returns true/false if the boolean value is a _boolean literal_ versus
67
+ * just the wider _boolean_ type.
68
+ */
69
+ export type IsBooleanLiteral<T extends Narrowable> = IsTrue<T> extends true
70
+ ? true
71
+ : IsFalse<T> extends true
72
+ ? true
73
+ : false;
74
+
75
+ /**
76
+ * **IfBooleanLiteral**
77
+ *
78
+ * Branch utility which returns `IF` type when `T` is a boolean literal and `ELSE` otherwise
79
+ */
80
+ export type IfBooleanLiteral<
81
+ T extends boolean,
82
+ IF extends Narrowable,
83
+ ELSE extends Narrowable
84
+ > = IsBooleanLiteral<T> extends true ? IF : ELSE;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * **Equal**`<X,Y>`
3
+ *
4
+ * Type utility which tests whether two types -- `X` and `Y` -- are exactly the same type
5
+ */
6
+ export type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2
7
+ ? true
8
+ : false;
9
+
10
+ /**
11
+ * **NotEqual**`<X,Y>`
12
+ *
13
+ * Type utility which tests whether two types -- `X` and `Y` -- are _not_ exactly the same type
14
+ */
15
+ export type NotEqual<X, Y> = true extends Equal<X, Y> ? false : true;