inferred-types 0.33.3 → 0.34.0

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 (44) hide show
  1. package/.vscode/settings.json +1 -0
  2. package/dist/index.d.ts +159 -76
  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 +12 -27
  13. package/src/runtime/type-checks/isUndefined.ts +1 -1
  14. package/src/runtime/type-checks/startsWith.ts +2 -2
  15. package/src/types/Mutable.ts +1 -1
  16. package/src/types/Narrowable.ts +1 -2
  17. package/src/types/{type-checks → boolean-logic}/EndsWith.ts +1 -1
  18. package/src/types/{type-checks → boolean-logic}/Extends.ts +3 -4
  19. package/src/types/{type-checks → boolean-logic}/Includes.ts +0 -0
  20. package/src/types/{type-checks → boolean-logic}/IsLiteral.ts +1 -1
  21. package/src/types/{type-checks → boolean-logic}/IsNumericLiteral.ts +0 -0
  22. package/src/types/{type-checks → boolean-logic}/IsScalar.ts +0 -0
  23. package/src/types/{type-checks → boolean-logic}/IsStringLiteral.ts +0 -0
  24. package/src/types/{type-checks → boolean-logic}/IsUndefined.ts +3 -3
  25. package/src/types/{type-checks → boolean-logic}/StartsWith.ts +1 -1
  26. package/src/types/{type-checks → boolean-logic}/TypeDefault.ts +1 -1
  27. package/src/types/boolean-logic/array.ts +57 -0
  28. package/src/types/boolean-logic/boolean.ts +76 -0
  29. package/src/types/{type-checks → boolean-logic}/index.ts +2 -1
  30. package/src/types/{type-checks → boolean-logic}/object.ts +0 -0
  31. package/src/types/{type-checks → boolean-logic}/string.ts +0 -0
  32. package/src/types/combinators/Or.ts +12 -0
  33. package/src/types/combinators/equivalency.ts +15 -0
  34. package/src/types/combinators/index.ts +2 -0
  35. package/src/types/dictionary/MapTo.ts +1 -1
  36. package/src/types/functions/LogicFunction.ts +1 -1
  37. package/src/types/index.ts +2 -1
  38. package/tests/boolean-logic/Contains.test.ts +55 -0
  39. package/tests/{TypeInfo → boolean-logic}/IsLiteral.spec.ts +0 -0
  40. package/tests/dictionary/{PrependValuesWithFunction.ts → PrependValuesWithFunction.test.ts} +0 -0
  41. package/tests/dictionary/TypeDefault.test.ts +1 -1
  42. package/tests/lists/Length.test.ts +19 -0
  43. package/tests/runtime/if-is.spec.ts +103 -2
  44. package/src/types/type-checks/IsBooleanLiteral.ts +0 -16
@@ -9,6 +9,7 @@
9
9
  "Dasherize",
10
10
  "dasherized",
11
11
  "Decomp",
12
+ "foey",
12
13
  "foofoo",
13
14
  "fooy",
14
15
  "ruleset",
package/dist/index.d.ts CHANGED
@@ -141,6 +141,97 @@ type Keys<T extends Record<string, any> | readonly string[], W extends string |
141
141
  */
142
142
  type Length<T extends readonly any[]> = T["length"];
143
143
 
144
+ /**
145
+ * **Equal**`<X,Y>`
146
+ *
147
+ * Type utility which tests whether two types -- `X` and `Y` -- are exactly the same type
148
+ */
149
+ type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
150
+ /**
151
+ * **NotEqual**`<X,Y>`
152
+ *
153
+ * Type utility which tests whether two types -- `X` and `Y` -- are _not_ exactly the same type
154
+ */
155
+ type NotEqual<X, Y> = true extends Equal<X, Y> ? false : true;
156
+
157
+ /**
158
+ * **AfterFirst**`<T>`
159
+ *
160
+ * returns the elements in an array _after_ the first element
161
+ */
162
+ type AfterFirst<T extends readonly any[]> = T extends readonly [any, ...any[]] ? T extends readonly [any, ...infer Rest] ? Rest : never : T;
163
+
164
+ /**
165
+ * returns the first `string` value from an array of values
166
+ */
167
+ type FirstString<T> = T extends [infer S extends string, ...unknown[]] ? S : never;
168
+
169
+ /**
170
+ * **Split**`<T, SEP>`
171
+ *
172
+ * Splits a string literal `T` by string literal _separator_ `SEP`. The result is an array
173
+ * of string literals.
174
+ */
175
+ type Split<T extends string, SEP extends string, ANSWER extends string[] = []> = string extends T ? string[] : T extends SEP ? ANSWER : T extends `${infer HEAD}${SEP}${infer TAIL}` ? Split<TAIL, SEP, [...ANSWER, HEAD]> : [...ANSWER, T];
176
+
177
+ /**
178
+ * Get the type of a property of an object:
179
+ * ```ts
180
+ * const car = { make: "Chevy", model: "Malibu", }
181
+ * ```
182
+ */
183
+ type Get<T, K> = K extends `${infer FK}.${infer L}` ? FK extends keyof T ? Get<T[FK], L> : never : K extends keyof T ? T[K] : never;
184
+
185
+ /**
186
+ * A union of types used in conjunction with the `literalValues()` function
187
+ * to produce a _narrow_ type definition of a passed in dictionary object.
188
+ */
189
+ type Narrowable = string | number | boolean | symbol | object | undefined | void | null | {};
190
+
191
+ /**
192
+ * Create a union type based on a given property in an array of objects
193
+ * ```ts
194
+ * const data = [
195
+ * { id: 123, color: "blue" },
196
+ * { id: 456, color: "red" },
197
+ * ] as const;
198
+ * // 123 | 456
199
+ * type U = UniqueForProp<typeof data, "id">;
200
+ * ```
201
+ */
202
+ type UniqueForProp<T extends readonly Record<string, Narrowable>[], P extends string> = Readonly<Get<T[number], P>>;
203
+
204
+ type IsArray<T> = [T] extends [any[]] ? true : [T] extends [readonly any[]] ? true : false;
205
+ type IsReadonlyArray<T> = T extends readonly any[] ? true : false;
206
+ /**
207
+ * **IfArray**`<T, IF, ELSE>`
208
+ *
209
+ * Type utility which convert to type `IF` or `ELSE` based on whether `T` is an array
210
+ */
211
+ type IfArray<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable> = IsArray<T> extends true ? IF : ELSE;
212
+ /**
213
+ * **IfArray**`<T, IF, ELSE>`
214
+ *
215
+ * Type utility which convert to type `IF` or `ELSE` based on whether `T` is a readonly array
216
+ */
217
+ type IfReadonlyArray<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable> = IsReadonlyArray<T> extends true ? IF : ELSE;
218
+ /**
219
+ * **Contains**`<T, A>`
220
+ *
221
+ * Type utility which checks whether a type `T` exists within an array `A`. Result is
222
+ * `true` if `T` _extends_ any element in `A` making it match widely against `A`. If you
223
+ * prefer a narrower match you can use `NarrowlyContains<T,A>` instead.
224
+ */
225
+ type Contains<T extends Narrowable, A extends readonly any[]> = First<A> extends T ? true : [] extends AfterFirst<A> ? false : Contains<T, AfterFirst<A>>;
226
+ /**
227
+ * **NarrowlyContains**`<T, A>`
228
+ *
229
+ * Type utility which checks whether a type `T` exists within an array `A`. Result is
230
+ * `true` if `T` _extends_ any element in `A` making it match widely against `A`. If you
231
+ * prefer a wider match you can use `Contains<T,A>` instead.
232
+ */
233
+ type NarrowlyContains<T extends Narrowable, A extends readonly any[]> = Equal<First<A>, T> extends true ? true : [] extends AfterFirst<A> ? false : NarrowlyContains<T, AfterFirst<A>>;
234
+
144
235
  /**
145
236
  * Converts a Tuple type into a _union_ of the tuple elements
146
237
  * ```ts
@@ -168,6 +259,34 @@ type UnionToTuple<U, Last = LastInUnion<U>> = [U] extends [never] ? [] : [...Uni
168
259
 
169
260
  type Widen<T> = T extends string ? string : T extends number ? number : T extends boolean ? boolean : T;
170
261
 
262
+ type IsBoolean<T> = T extends boolean ? true : false;
263
+ /**
264
+ * Type utility which returns `true` or `false` based on
265
+ * whether the type holds the narrow "true" type.
266
+ * ```ts
267
+ * // true
268
+ * type T = IsTrue<true>;
269
+ * // boolean
270
+ * type U = IsTrue<boolean>;
271
+ * // false
272
+ * type F = IsTrue<false>;
273
+ * type F2 = IsTrue<"false">;
274
+ * ```
275
+ */
276
+ type IsTrue<T extends Narrowable> = IsBoolean<T> extends true ? T extends true ? true : T extends false ? false : unknown : false;
277
+ type IsFalse<T extends Narrowable> = IsBoolean<T> extends true ? T extends false ? true : true extends T ? false : unknown : false;
278
+ /**
279
+ * Type utility which checks for literal `true` value and then switches type
280
+ * to the IF, ELSE, or MAYBE generic types passed in where _maybe_ is when T
281
+ * is the wide type of `boolean`
282
+ */
283
+ type IfTrue<T, IF, ELSE, MAYBE> = IsTrue<T> extends true ? IF : IsTrue<T> extends false ? ELSE : MAYBE;
284
+ /**
285
+ * Type utility which checks for literal `false` value and then switches type
286
+ * to the IF, ELSE, or MAYBE generic types passed in where _maybe_ is when T
287
+ * is the wide type of `boolean`
288
+ */
289
+ type IfFalse<T, IF, ELSE, MAYBE> = IsFalse<T> extends true ? IF : IsTrue<T> extends false ? ELSE : MAYBE;
171
290
  /**
172
291
  * **IsBooleanLiteral**
173
292
  *
@@ -264,12 +383,6 @@ type IsScalar<T> = [T] extends [string] ? true : [T] extends [number] ? true : [
264
383
  */
265
384
  type IfScalar<T, IF, ELSE> = IsScalar<T> extends true ? IF : ELSE;
266
385
 
267
- /**
268
- * A union of types used in conjunction with the `literalValues()` function
269
- * to produce a _narrow_ type definition of a passed in dictionary object.
270
- */
271
- type Narrowable = string | number | boolean | symbol | object | undefined | void | null | {};
272
-
273
386
  /**
274
387
  * **IsUndefined**
275
388
  *
@@ -277,19 +390,19 @@ type Narrowable = string | number | boolean | symbol | object | undefined | void
277
390
  */
278
391
  type IsUndefined<T extends Narrowable> = T extends undefined ? true : false;
279
392
  /**
280
- * **IfUndefined**
393
+ * **IfUndefined**`<T, IF, ELSE>`
281
394
  *
282
- * Branch utility which returns `IF` type when `T` is an _undefined_ value
283
- * otherwise returns `ELSE` type
395
+ * Type utility which returns `IF` type when `T` is an _undefined_
396
+ * otherwise returns `ELSE` type.
284
397
  */
285
398
  type IfUndefined<T, IF, ELSE> = IsUndefined<T> extends true ? IF : ELSE;
286
399
 
287
400
  /**
288
- * **Extends**
401
+ * **Extends**`<T, EXTENDS>`
289
402
  *
290
- * Boolean type utility which returns `true` if `E` _extends_ `T`.
403
+ * Boolean type utility which returns `true` if `T` _extends_ `EXTENDS`.
291
404
  */
292
- type Extends<E, T> = E extends T ? true : false;
405
+ type Extends<T, EXTENDS> = T extends EXTENDS ? true : false;
293
406
  /**
294
407
  * **IfExtends**
295
408
  *
@@ -1212,14 +1325,6 @@ O extends (...args: any[]) => any = (...args: any[]) => any> = SimplifyObject<{
1212
1325
  [K in keyof T]: T[K] extends O ? T[K] extends (...args: infer A) => any ? Record<K, (...args: A) => R> : Record<K, T[K]> : Record<K, T[K]>;
1213
1326
  }[keyof T]>;
1214
1327
 
1215
- /**
1216
- * Get the type of a property of an object:
1217
- * ```ts
1218
- * const car = { make: "Chevy", model: "Malibu", }
1219
- * ```
1220
- */
1221
- type Get<T, K> = K extends `${infer FK}.${infer L}` ? FK extends keyof T ? Get<T[FK], L> : never : K extends keyof T ? T[K] : never;
1222
-
1223
1328
  /**
1224
1329
  * Expresses whether an option is "opt" (optional) or "req" (required)
1225
1330
  */
@@ -1544,7 +1649,7 @@ type FinalReturn<T extends any> = T extends (...args: any[]) => any ? FinalRetur
1544
1649
  /**
1545
1650
  * A function which returns a boolean value
1546
1651
  */
1547
- type LogicFunction<T extends any[]> = (...args: T) => boolean;
1652
+ type LogicFunction<T extends readonly any[]> = (...args: T) => boolean;
1548
1653
 
1549
1654
  type DictFromKv<T extends readonly {
1550
1655
  key: string;
@@ -1594,37 +1699,11 @@ type KvFrom<T extends object> = Array<{
1594
1699
  type KvTuple<T, K extends keyof T> = [K, Record<K, T[K]>];
1595
1700
 
1596
1701
  /**
1597
- * **AfterFirst**`<T>`
1702
+ * **Or**`<T>`
1598
1703
  *
1599
- * returns the elements in an array _after_ the first element
1704
+ * Takes an array of boolean values and produces a boolean OR across these values
1600
1705
  */
1601
- type AfterFirst<T extends readonly any[]> = T extends readonly [any, ...any[]] ? T extends readonly [any, ...infer Rest] ? Rest : never : T;
1602
-
1603
- /**
1604
- * returns the first `string` value from an array of values
1605
- */
1606
- type FirstString<T> = T extends [infer S extends string, ...unknown[]] ? S : never;
1607
-
1608
- /**
1609
- * **Split**`<T, SEP>`
1610
- *
1611
- * Splits a string literal `T` by string literal _separator_ `SEP`. The result is an array
1612
- * of string literals.
1613
- */
1614
- type Split<T extends string, SEP extends string, ANSWER extends string[] = []> = string extends T ? string[] : T extends SEP ? ANSWER : T extends `${infer HEAD}${SEP}${infer TAIL}` ? Split<TAIL, SEP, [...ANSWER, HEAD]> : [...ANSWER, T];
1615
-
1616
- /**
1617
- * Create a union type based on a given property in an array of objects
1618
- * ```ts
1619
- * const data = [
1620
- * { id: 123, color: "blue" },
1621
- * { id: 456, color: "red" },
1622
- * ] as const;
1623
- * // 123 | 456
1624
- * type U = UniqueForProp<typeof data, "id">;
1625
- * ```
1626
- */
1627
- type UniqueForProp<T extends readonly Record<string, Narrowable>[], P extends string> = Readonly<Get<T[number], P>>;
1706
+ type Or<T extends readonly boolean[]> = NarrowlyContains<true, T> extends true ? true : NarrowlyContains<boolean, T> extends true ? boolean : false;
1628
1707
 
1629
1708
  type DictArrayFilterCallback<K extends keyof T, T extends object, R extends true | false> = (key: K, value: Pick<T, K>) => R;
1630
1709
  /**
@@ -1738,13 +1817,7 @@ declare const api: <N extends Narrowable, TPrivate extends Readonly<Record<any,
1738
1817
  */
1739
1818
  declare const and: <T extends any[]>(...ops: readonly LogicFunction<T>[]) => LogicFunction<T>;
1740
1819
 
1741
- /**
1742
- * Groups a number of "logic functions" together by combining their results using
1743
- * the logical **OR** operator.
1744
- *
1745
- * **Note:** a "logic function" is any function which returns a boolean
1746
- */
1747
- declare const or: <T extends any[]>(...ops: LogicFunction<T>[]) => LogicFunction<T>;
1820
+ declare function or<O extends readonly boolean[]>(...conditions: O): Or<O>;
1748
1821
 
1749
1822
  /**
1750
1823
  * Groups a number of "logic functions" together by combining their results using
@@ -2165,10 +2238,15 @@ type SuggestNumeric<T extends number> = T | (number & {});
2165
2238
  type Condition<TInput extends Narrowable, TResult extends boolean> = (input: TInput) => TResult;
2166
2239
  declare const condition: <TInput extends Narrowable, C extends Condition<Narrowable, boolean>>(c: C, input: TInput) => boolean;
2167
2240
 
2168
- type IsArray<T> = T extends any[] ? true : false;
2169
2241
  declare function isArray<T>(i: T): IsArray<T>;
2242
+ /**
2243
+ * **ifArray**(T, IF, ELSE)
2244
+ *
2245
+ * A utility which evaluates a type `T` for whether it is an array and then
2246
+ */
2247
+ declare function ifArray<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable>(val: T, isAnArray: <N extends T & readonly any[]>(arr: N) => IF, isNotAnArray: <N extends Exclude<T, any[]>>(nonArr: N) => ELSE): IfArray<T, IF, ELSE>;
2248
+ declare function ifArrayPartial<T extends Narrowable>(): <IF extends Narrowable, ELSE extends Narrowable>(isAnArray: <N extends T & readonly any[]>(arr: N) => IF, isNotAnArray: <N_1 extends Exclude<T, any[]>>(nonArr: N_1) => ELSE) => <V extends T>(val: V) => IfArray<V, IF, ELSE>;
2170
2249
 
2171
- type IsBoolean<T> = T extends boolean ? true : false;
2172
2250
  /**
2173
2251
  * Runtime and type checks whether a variable is a boolean value.
2174
2252
  */
@@ -2186,8 +2264,23 @@ declare function isBoolean<T extends any>(i: T): IsBoolean<T>;
2186
2264
  */
2187
2265
  declare function ifBoolean<T, IF, ELSE>(val: T, ifVal: IF, elseVal: ELSE): IsBoolean<T> extends true ? IF : ELSE;
2188
2266
 
2189
- type IsFalse<T extends Narrowable> = IsBoolean<T> extends true ? T extends false ? true : true extends T ? false : unknown : false;
2190
2267
  declare function isFalse<T>(i: T): IsFalse<T>;
2268
+ /**
2269
+ * **ifTrue**
2270
+ *
2271
+ * Strongly type-aware conditional statement which checks whether a value is
2272
+ * a _true_ and returns one of two values (strongly typed) based on the evaluation
2273
+ * of this criteria.
2274
+ *
2275
+ * @param val the value being tested
2276
+ * @param ifVal the value (strongly typed) returned if val is _true_ value
2277
+ * @param elseVal the value (strongly typed) returned if val is NOT a _true_ value
2278
+ *
2279
+ * Note: at runtime there's no way to distinguish if the value was widely or loosely
2280
+ * typed so unlike the type utility there is no "MAYBE" state but if a wide type if
2281
+ * encountered the _type_ will the union of `IF` and `ELSE`.
2282
+ */
2283
+ declare function ifFalse<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifVal: IF, elseVal: ELSE): IfFalse<T, IF, ELSE, IF | ELSE>;
2191
2284
 
2192
2285
  type IsFunction<T> = T extends FunctionType ? true : false;
2193
2286
  type HybridFunction<TProps extends {}> = (<TArgs extends any[]>(...args: TArgs) => any) & TProps;
@@ -2287,20 +2380,6 @@ declare function ifString<T extends Narrowable, IF extends Narrowable, ELSE exte
2287
2380
 
2288
2381
  declare function isSymbol<T>(i: T): T extends symbol ? true : false;
2289
2382
 
2290
- /**
2291
- * Type utility which returns `true` or `false` based on
2292
- * whether the type holds the narrow "true" type.
2293
- * ```ts
2294
- * // true
2295
- * type T = IsTrue<true>;
2296
- * // unknown
2297
- * type U = IsTrue<boolean>;
2298
- * // false
2299
- * type F = IsTrue<false>;
2300
- * type F2 = IsTrue<"false">;
2301
- * ```
2302
- */
2303
- type IsTrue<T> = IsBoolean<T> extends true ? T extends true ? true : T extends false ? false : unknown : false;
2304
2383
  /**
2305
2384
  * Run-time and type checking of whether a variable is `true`.
2306
2385
  */
@@ -2315,8 +2394,12 @@ declare function isTrue<T extends Narrowable>(i: T): IsTrue<T>;
2315
2394
  * @param val the value being tested
2316
2395
  * @param ifVal the value (strongly typed) returned if val is _true_ value
2317
2396
  * @param elseVal the value (strongly typed) returned if val is NOT a _true_ value
2397
+ *
2398
+ * Note: at runtime there's no way to distinguish if the value was widely or loosely
2399
+ * typed so unlike the type utility there is no "MAYBE" state but if a wide type if
2400
+ * encountered the _type_ will the union of `IF` and `ELSE`.
2318
2401
  */
2319
- declare function ifTrue<T extends Narrowable, IF, ELSE>(val: T, ifVal: IF, elseVal: ELSE): IsTrue<T> extends true ? IF : ELSE;
2402
+ declare function ifTrue<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifVal: IF, elseVal: ELSE): IfTrue<T, IF, ELSE, IF | ELSE>;
2320
2403
 
2321
2404
  declare function isUndefined<T extends Narrowable>(i: T): undefined extends T ? true : false;
2322
2405
  /**
@@ -2440,4 +2523,4 @@ interface IFluentConfigurator<C> {
2440
2523
  */
2441
2524
  declare function FluentConfigurator<I>(initial?: I): IFluentConfigurator<{}>;
2442
2525
 
2443
- export { AfterFirst, AllCaps, Alpha, AlphaNumeric, AnyFunction, Api, ApiFunction, ApiValue, AppendToDictionary, AppendToObject, ArrConcat, Array$1 as Array, ArrayConverter, AsArray, AsFinalizedConfig, AssertExtends, Box, BoxValue, BoxedFnParams, BoxedReturn, Bracket, Break, CamelCase, CapitalizeWords, Cardinality, Cardinality0, Cardinality1, CardinalityExplicit, CardinalityFilter0, CardinalityFilter1, CardinalityIn, CardinalityInput, CardinalityNode, CardinalityOut, CardinalityTuple, ClosingBracket, Condition, ConditionFilter, Configurator, ConfiguredMap, Constructor, DEFAULT_MANY_TO_ONE_MAPPING, DEFAULT_ONE_TO_MANY_MAPPING, DEFAULT_ONE_TO_ONE_MAPPING, DashToSnake, DashUppercase, Dasherize, DecomposeMapConfig, DefaultManyToOneMapping, DefaultOneToManyMapping, DefaultOneToOneMapping, DefinePropertiesApi, DictArrApi, DictArray, DictArrayFilterCallback, DictArrayKv, DictChangeValue, DictFromKv, DictKvTuple, DictPartialApplication, DictPrependWithFn, DictReturnValues, DomainName, DynamicRule, DynamicRuleSet, Email, EndsWith, EnumValues, ExpandRecursively, ExpectExtends, ExplicitFunction, Extends, FilterContains, FilterDefn, FilterEnds, FilterEquals, FilterFn, FilterGreaterThan, FilterIs, FilterLessThan, FilterNotEqual, FilterStarts, FinalReturn, FinalizedMapConfig, First, FirstKey, FirstKeyValue, FirstOfEach, FirstOrUndefined, FirstString, FluentConfigurator, FluentFunction, FnShape, FromDictArray, FullyQualifiedUrl, FunctionType, GeneralDictionary, Get, HasUppercase, HybridFunction, IConfigurator, IFluentConfigurator, If, IfBooleanLiteral, IfExtends, IfExtendsThen, IfLiteral, IfNumericLiteral, IfObject, IfOptionalLiteral, IfScalar, IfStartsWith, IfStringLiteral, IfUndefined, Include, Includes, IntersectingKeys, Ipv4, IsArray, IsBoolean, IsBooleanLiteral, IsCapitalized, IsFalse, IsFunction, IsLiteral, IsNull, IsNumber, IsNumericLiteral, IsObject, IsOptionalLiteral, IsScalar, IsStringLiteral, IsTrue, IsUndefined, KebabCase, KeyValue, KeyedRecord, Keys, KeysWithValue, KvFrom, KvTuple, LastInUnion, LeftWhitespace, Length, LogicFunction, LogicalCombinator, LowerAllCaps, LowerAlpha, ManyToMany, ManyToOne, ManyToZero, MapCard, MapCardinality, MapCardinalityFrom, MapCardinalityIllustrated, MapConfig, MapFn, MapFnInput, MapFnOutput, MapIR, MapInput, MapInputFrom, MapOR, MapOutput, MapOutputFrom, MapTo, Mapper, MapperApi, MaybeFalse, MaybeTrue, Mutable, MutableProps, NarrowBox, Narrowable, NetworkProtocol, NonAlpha, NonNumericKeys, NonStringKeys, Not, NotFilter, Numeric, NumericFilter, NumericKeys, NumericString, ObjectType, OneToMany, OneToOne, OneToZero, Opaque, OpeningBracket, OptRequired, OptionalKeys, OptionalProps, Parenthesis, PascalCase, Pluralize, PrivateKey, PrivateKeys, PublicKeys, Punctuation, PureFluentApi, RelativeUrl, Replace, RequireProps, RequiredKeys, RequiredProps, Retain, RightWhitespace, RuleDefinition, RuntimeProp, RuntimeType, SameKeys, SecondOfEach, SimpleFunction, SimplifyObject, SnakeCase, SpecialCharacters, Split, StartsWith, StringDelimiter, StringFilter, StringKeys, StringLength, Suggest, SuggestNumeric, ToFluent, Transformer, Trim, TrimLeft, TrimRight, TupleToUnion, Type, TypeApi, TypeDefault, TypeDefinition, TypeGuard, TypeOptions, Unbox, UndefinedArrayIsUnknown, UndefinedTreatment, UndefinedValue, UnionToIntersection, UnionToTuple, UniqueDictionary, UniqueForProp, Uniqueness, UnwrapNot, UpperAlpha, UrlBuilder, VariableName, Where, WhereNot, Whitespace, Widen, WithNumericKeys, WithStringKeys, WithValue, ZeroToMany, ZeroToOne, ZeroToZero, ZipCode, and, api, arrayToKeyLookup, arrayToObject, asArray, box, condition, createFnWithProps, defineProperties, defineType, dictArr, dictToKv, dictionaryTransform, entries, filter, filterDictArray, fnWithProps, groupBy, idLiteral, idTypeGuard, identity, ifBoolean, ifNull, ifNumber, ifString, ifTrue, ifUndefined, isArray, isBoolean, isBox, isFalse, isFunction, isNotFilter, isNull, isNumber, isNumericFilter, isObject, isString, isSymbol, isTrue, isType, isUndefined, keys, kindLiteral, kv, kvToDict, literal, mapTo, mapToDict, mapToFn, mapValues, nameLiteral, not, or, readonlyFnWithProps, ruleSet, strArrayToDict, type, typeApi, unbox, withValue };
2526
+ export { AfterFirst, AllCaps, Alpha, AlphaNumeric, AnyFunction, Api, ApiFunction, ApiValue, AppendToDictionary, AppendToObject, ArrConcat, Array$1 as Array, ArrayConverter, AsArray, AsFinalizedConfig, AssertExtends, Box, BoxValue, BoxedFnParams, BoxedReturn, Bracket, Break, CamelCase, CapitalizeWords, Cardinality, Cardinality0, Cardinality1, CardinalityExplicit, CardinalityFilter0, CardinalityFilter1, CardinalityIn, CardinalityInput, CardinalityNode, CardinalityOut, CardinalityTuple, ClosingBracket, Condition, ConditionFilter, Configurator, ConfiguredMap, Constructor, Contains, DEFAULT_MANY_TO_ONE_MAPPING, DEFAULT_ONE_TO_MANY_MAPPING, DEFAULT_ONE_TO_ONE_MAPPING, DashToSnake, DashUppercase, Dasherize, DecomposeMapConfig, DefaultManyToOneMapping, DefaultOneToManyMapping, DefaultOneToOneMapping, DefinePropertiesApi, DictArrApi, DictArray, DictArrayFilterCallback, DictArrayKv, DictChangeValue, DictFromKv, DictKvTuple, DictPartialApplication, DictPrependWithFn, DictReturnValues, DomainName, DynamicRule, DynamicRuleSet, Email, EndsWith, EnumValues, Equal, ExpandRecursively, ExpectExtends, ExplicitFunction, Extends, FilterContains, FilterDefn, FilterEnds, FilterEquals, FilterFn, FilterGreaterThan, FilterIs, FilterLessThan, FilterNotEqual, FilterStarts, FinalReturn, FinalizedMapConfig, First, FirstKey, FirstKeyValue, FirstOfEach, FirstOrUndefined, FirstString, FluentConfigurator, FluentFunction, FnShape, FromDictArray, FullyQualifiedUrl, FunctionType, GeneralDictionary, Get, HasUppercase, HybridFunction, IConfigurator, IFluentConfigurator, If, IfArray, IfBooleanLiteral, IfExtends, IfExtendsThen, IfFalse, IfLiteral, IfNumericLiteral, IfObject, IfOptionalLiteral, IfReadonlyArray, IfScalar, IfStartsWith, IfStringLiteral, IfTrue, IfUndefined, Include, Includes, IntersectingKeys, Ipv4, IsArray, IsBoolean, IsBooleanLiteral, IsCapitalized, IsFalse, IsFunction, IsLiteral, IsNull, IsNumber, IsNumericLiteral, IsObject, IsOptionalLiteral, IsReadonlyArray, IsScalar, IsStringLiteral, IsTrue, IsUndefined, KebabCase, KeyValue, KeyedRecord, Keys, KeysWithValue, KvFrom, KvTuple, LastInUnion, LeftWhitespace, Length, LogicFunction, LogicalCombinator, LowerAllCaps, LowerAlpha, ManyToMany, ManyToOne, ManyToZero, MapCard, MapCardinality, MapCardinalityFrom, MapCardinalityIllustrated, MapConfig, MapFn, MapFnInput, MapFnOutput, MapIR, MapInput, MapInputFrom, MapOR, MapOutput, MapOutputFrom, MapTo, Mapper, MapperApi, MaybeFalse, MaybeTrue, Mutable, MutableProps, NarrowBox, Narrowable, NarrowlyContains, NetworkProtocol, NonAlpha, NonNumericKeys, NonStringKeys, Not, NotEqual, NotFilter, Numeric, NumericFilter, NumericKeys, NumericString, ObjectType, OneToMany, OneToOne, OneToZero, Opaque, OpeningBracket, OptRequired, OptionalKeys, OptionalProps, Or, Parenthesis, PascalCase, Pluralize, PrivateKey, PrivateKeys, PublicKeys, Punctuation, PureFluentApi, RelativeUrl, Replace, RequireProps, RequiredKeys, RequiredProps, Retain, RightWhitespace, RuleDefinition, RuntimeProp, RuntimeType, SameKeys, SecondOfEach, SimpleFunction, SimplifyObject, SnakeCase, SpecialCharacters, Split, StartsWith, StringDelimiter, StringFilter, StringKeys, StringLength, Suggest, SuggestNumeric, ToFluent, Transformer, Trim, TrimLeft, TrimRight, TupleToUnion, Type, TypeApi, TypeDefault, TypeDefinition, TypeGuard, TypeOptions, Unbox, UndefinedArrayIsUnknown, UndefinedTreatment, UndefinedValue, UnionToIntersection, UnionToTuple, UniqueDictionary, UniqueForProp, Uniqueness, UnwrapNot, UpperAlpha, UrlBuilder, VariableName, Where, WhereNot, Whitespace, Widen, WithNumericKeys, WithStringKeys, WithValue, ZeroToMany, ZeroToOne, ZeroToZero, ZipCode, and, api, arrayToKeyLookup, arrayToObject, asArray, box, condition, createFnWithProps, defineProperties, defineType, dictArr, dictToKv, dictionaryTransform, entries, filter, filterDictArray, fnWithProps, groupBy, idLiteral, idTypeGuard, identity, ifArray, ifArrayPartial, ifBoolean, ifFalse, ifNull, ifNumber, ifString, ifTrue, ifUndefined, isArray, isBoolean, isBox, isFalse, isFunction, isNotFilter, isNull, isNumber, isNumericFilter, isObject, isString, isSymbol, isTrue, isType, isUndefined, keys, kindLiteral, kv, kvToDict, literal, mapTo, mapToDict, mapToFn, mapValues, nameLiteral, not, or, readonlyFnWithProps, ruleSet, strArrayToDict, type, typeApi, unbox, withValue };
package/dist/index.js CHANGED
@@ -48,7 +48,10 @@ __export(src_exports, {
48
48
  idLiteral: () => idLiteral,
49
49
  idTypeGuard: () => idTypeGuard,
50
50
  identity: () => identity,
51
+ ifArray: () => ifArray,
52
+ ifArrayPartial: () => ifArrayPartial,
51
53
  ifBoolean: () => ifBoolean,
54
+ ifFalse: () => ifFalse,
52
55
  ifNull: () => ifNull,
53
56
  ifNumber: () => ifNumber,
54
57
  ifString: () => ifString,
@@ -151,12 +154,9 @@ var and = (...ops) => {
151
154
  };
152
155
 
153
156
  // src/runtime/combinators/or.ts
154
- var or = (...ops) => {
155
- const fn = (...args) => {
156
- return [...ops].some((i) => i(...args));
157
- };
158
- return fn;
159
- };
157
+ function or(...conditions) {
158
+ return conditions.some((v) => v === true) ? true : false;
159
+ }
160
160
 
161
161
  // src/runtime/combinators/not.ts
162
162
  var not = (op) => {
@@ -175,6 +175,14 @@ var condition = (c, input) => {
175
175
  function isArray(i) {
176
176
  return Array.isArray(i) === true;
177
177
  }
178
+ function ifArray(val, isAnArray, isNotAnArray) {
179
+ return isArray(val) ? isAnArray(val) : isNotAnArray(val);
180
+ }
181
+ function ifArrayPartial() {
182
+ return (isAnArray, isNotAnArray) => {
183
+ return (val) => ifArray(val, isAnArray, isNotAnArray);
184
+ };
185
+ }
178
186
 
179
187
  // src/runtime/type-checks/isBoolean.ts
180
188
  function isBoolean(i) {
@@ -188,6 +196,9 @@ function ifBoolean(val, ifVal, elseVal) {
188
196
  function isFalse(i) {
189
197
  return typeof i === "boolean" && !i;
190
198
  }
199
+ function ifFalse(val, ifVal, elseVal) {
200
+ return isFalse(val) ? ifVal : elseVal;
201
+ }
191
202
 
192
203
  // src/runtime/type-checks/isFunction.ts
193
204
  function isFunction(input) {
@@ -795,7 +806,10 @@ function literal(obj) {
795
806
  idLiteral,
796
807
  idTypeGuard,
797
808
  identity,
809
+ ifArray,
810
+ ifArrayPartial,
798
811
  ifBoolean,
812
+ ifFalse,
799
813
  ifNull,
800
814
  ifNumber,
801
815
  ifString,
package/dist/index.mjs CHANGED
@@ -58,12 +58,9 @@ var and = (...ops) => {
58
58
  };
59
59
 
60
60
  // src/runtime/combinators/or.ts
61
- var or = (...ops) => {
62
- const fn = (...args) => {
63
- return [...ops].some((i) => i(...args));
64
- };
65
- return fn;
66
- };
61
+ function or(...conditions) {
62
+ return conditions.some((v) => v === true) ? true : false;
63
+ }
67
64
 
68
65
  // src/runtime/combinators/not.ts
69
66
  var not = (op) => {
@@ -82,6 +79,14 @@ var condition = (c, input) => {
82
79
  function isArray(i) {
83
80
  return Array.isArray(i) === true;
84
81
  }
82
+ function ifArray(val, isAnArray, isNotAnArray) {
83
+ return isArray(val) ? isAnArray(val) : isNotAnArray(val);
84
+ }
85
+ function ifArrayPartial() {
86
+ return (isAnArray, isNotAnArray) => {
87
+ return (val) => ifArray(val, isAnArray, isNotAnArray);
88
+ };
89
+ }
85
90
 
86
91
  // src/runtime/type-checks/isBoolean.ts
87
92
  function isBoolean(i) {
@@ -95,6 +100,9 @@ function ifBoolean(val, ifVal, elseVal) {
95
100
  function isFalse(i) {
96
101
  return typeof i === "boolean" && !i;
97
102
  }
103
+ function ifFalse(val, ifVal, elseVal) {
104
+ return isFalse(val) ? ifVal : elseVal;
105
+ }
98
106
 
99
107
  // src/runtime/type-checks/isFunction.ts
100
108
  function isFunction(input) {
@@ -701,7 +709,10 @@ export {
701
709
  idLiteral,
702
710
  idTypeGuard,
703
711
  identity,
712
+ ifArray,
713
+ ifArrayPartial,
704
714
  ifBoolean,
715
+ ifFalse,
705
716
  ifNull,
706
717
  ifNumber,
707
718
  ifString,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inferred-types",
3
- "version": "0.33.3",
3
+ "version": "0.34.0",
4
4
  "description": "Functions which provide useful type inference on TS projects",
5
5
  "license": "MIT",
6
6
  "author": "Ken Snyder<ken@ken.net>",
@@ -22,11 +22,11 @@
22
22
  "watch:bundle": "npx tsup src/index.ts --dts --format=esm,cjs --watch",
23
23
  "clean": "rimraf dist/**/*",
24
24
  "lint": "eslint src/**/*.ts --fix && tsc --noEmit ",
25
- "lint:full": "eslint src/**/*.ts && eslint test/**/*.ts && tsc --noEmit",
25
+ "lint:full": "eslint src/**/*.ts && eslint tests/**/*.ts && tsc --noEmit",
26
26
  "test": "vitest",
27
27
  "test:ci": "vitest run",
28
28
  "audit:fix": "pnpm audit --fix",
29
- "release": "run-s lint release:latest test:ci audit:fix release:bump",
29
+ "release": "run-s lint:full release:latest test:ci audit:fix release:bump",
30
30
  "release:latest": "pnpm install",
31
31
  "release:bump": "bumpp"
32
32
  },
@@ -1,15 +1,5 @@
1
- import { LogicFunction } from "src/types/functions";
1
+ import { Or } from "src/types/combinators/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 Narrowable, 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`.
@@ -41,7 +18,15 @@ export function isTrue<T extends Narrowable>(i: T) {
41
18
  * @param val the value being tested
42
19
  * @param ifVal the value (strongly typed) returned if val is _true_ value
43
20
  * @param elseVal the value (strongly typed) returned if val is NOT a _true_ value
21
+ *
22
+ * Note: at runtime there's no way to distinguish if the value was widely or loosely
23
+ * typed so unlike the type utility there is no "MAYBE" state but if a wide type if
24
+ * encountered the _type_ will the union of `IF` and `ELSE`.
44
25
  */
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;
26
+ export function ifTrue<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable>(
27
+ val: T,
28
+ ifVal: IF,
29
+ elseVal: ELSE
30
+ ) {
31
+ return (isTrue(val) ? ifVal : elseVal) as IfTrue<T, IF, ELSE, IF | ELSE>;
47
32
  }
@@ -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,5 @@
1
- import { IfStartsWith, StartsWith } from "src/types/type-checks";
2
- import { IfUndefined } from "src/types/type-checks/IsUndefined";
1
+ import { IfStartsWith, StartsWith } from "src/types/boolean-logic";
2
+ import { IfUndefined } from "src/types/boolean-logic/IsUndefined";
3
3
  import { createFnWithProps } from "../createFnWithProps";
4
4
  import { box, Box } from "../literals";
5
5
  import { ifTrue } from "./isTrue";
@@ -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 | {};
@@ -1,4 +1,4 @@
1
- import { IfStringLiteral } from "src/types/type-checks";
1
+ import { IfStringLiteral } from "src/types/boolean-logic";
2
2
 
3
3
  /**
4
4
  * **EndsWith**<T,U>
@@ -1,10 +1,9 @@
1
1
  /**
2
- * **Extends**
2
+ * **Extends**`<T, EXTENDS>`
3
3
  *
4
- * Boolean type utility which returns `true` if `E` _extends_ `T`.
4
+ * Boolean type utility which returns `true` if `T` _extends_ `EXTENDS`.
5
5
  */
6
- export type Extends<E, T> = E extends T ? true : false;
7
-
6
+ export type Extends<T, EXTENDS> = T extends EXTENDS ? true : false;
8
7
  /**
9
8
  * **IfExtends**
10
9
  *
@@ -1,4 +1,4 @@
1
- import { IsBooleanLiteral } from "./IsBooleanLiteral";
1
+ import { IsBooleanLiteral } from "./boolean";
2
2
  import { IsStringLiteral } from "./IsStringLiteral";
3
3
  import { IsNumericLiteral } from "./IsNumericLiteral";
4
4
 
@@ -8,9 +8,9 @@ import { Narrowable } from "../Narrowable";
8
8
  export type IsUndefined<T extends Narrowable> = T extends undefined ? true : false;
9
9
 
10
10
  /**
11
- * **IfUndefined**
11
+ * **IfUndefined**`<T, IF, ELSE>`
12
12
  *
13
- * Branch utility which returns `IF` type when `T` is an _undefined_ value
14
- * otherwise returns `ELSE` type
13
+ * Type utility which returns `IF` type when `T` is an _undefined_
14
+ * otherwise returns `ELSE` type.
15
15
  */
16
16
  export type IfUndefined<T, IF, ELSE> = IsUndefined<T> extends true ? IF : ELSE;
@@ -1,4 +1,4 @@
1
- import { IfStringLiteral } from "src/types/type-checks";
1
+ import { IfStringLiteral } from "src/types/boolean-logic";
2
2
  import { Narrowable } from "../Narrowable";
3
3
  /**
4
4
  * **StartsWith**<TValue, TStartsWith>
@@ -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 "../combinators/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,76 @@
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<T, IF, ELSE, MAYBE> = IsTrue<T> extends true
45
+ ? IF
46
+ : IsTrue<T> extends false
47
+ ? ELSE
48
+ : MAYBE;
49
+
50
+ /**
51
+ * Type utility which checks for literal `false` value and then switches type
52
+ * to the IF, ELSE, or MAYBE generic types passed in where _maybe_ is when T
53
+ * is the wide type of `boolean`
54
+ */
55
+ export type IfFalse<T, IF, ELSE, MAYBE> = IsFalse<T> extends true
56
+ ? IF
57
+ : IsTrue<T> extends false
58
+ ? ELSE
59
+ : MAYBE;
60
+
61
+ /**
62
+ * **IsBooleanLiteral**
63
+ *
64
+ * Type utility which returns true/false if the boolean value is a _boolean literal_ versus
65
+ * just the wider _boolean_ type.
66
+ */
67
+ export type IsBooleanLiteral<T extends boolean> = boolean extends T ? false : true;
68
+
69
+ /**
70
+ * **IfBooleanLiteral**
71
+ *
72
+ * Branch utility which returns `IF` type when `T` is a boolean literal and `ELSE` otherwise
73
+ */
74
+ export type IfBooleanLiteral<T extends boolean, IF, ELSE> = IsBooleanLiteral<T> extends true
75
+ ? IF
76
+ : ELSE;
@@ -1,5 +1,6 @@
1
+ export * from "./array";
1
2
  export * from "./Includes";
2
- export * from "./IsBooleanLiteral";
3
+ export * from "./boolean";
3
4
  export * from "./IsNumericLiteral";
4
5
  export * from "./IsScalar";
5
6
  export * from "./IsStringLiteral";
@@ -0,0 +1,12 @@
1
+ import { NarrowlyContains } from "../boolean-logic";
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;
@@ -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;
@@ -0,0 +1,2 @@
1
+ export * from "./equivalency";
2
+ export * from "./Or";
@@ -6,7 +6,7 @@ import {
6
6
  DefaultOneToOneMapping,
7
7
  } from "src/runtime/dictionary/mapTo";
8
8
  import { EnumValues } from "../EnumValues";
9
- import { TypeDefault } from "../type-checks/TypeDefault";
9
+ import { TypeDefault } from "../boolean-logic/TypeDefault";
10
10
 
11
11
  /**
12
12
  * Expresses relationship between inputs/outputs:
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * A function which returns a boolean value
3
3
  */
4
- export type LogicFunction<T extends any[]> = (...args: T) => boolean;
4
+ export type LogicFunction<T extends readonly any[]> = (...args: T) => boolean;
@@ -37,11 +37,12 @@ export * from "./fluent/index";
37
37
  export * from "./functions/index";
38
38
  export * from "./kv/index";
39
39
  export * from "./lists/index";
40
+ export * from "./combinators/index";
40
41
  export * from "./literal-unions/index";
41
42
  export * from "./string-literals/index";
42
43
  export * from "./tuples/index";
43
44
  export * from "./type-conversion/index";
44
- export * from "./type-checks/index";
45
+ export * from "./boolean-logic/index";
45
46
 
46
47
  // #endregion auto-indexed files
47
48
 
@@ -0,0 +1,55 @@
1
+ import { Equal, Expect } from "@type-challenges/utils";
2
+ import { Contains, NarrowlyContains } from "src/types/boolean-logic/array";
3
+ import { describe, it } from "vitest";
4
+
5
+ describe("Contains<T,A>", () => {
6
+ it("happy-path", () => {
7
+ type T1 = [number, 32, 64, "foo"];
8
+ type T2 = [false, true];
9
+ type T3 = [42, 64, 128];
10
+ type T4 = ["foo", "bar"];
11
+
12
+ type cases = [
13
+ // "foo" extends string so true
14
+ Expect<Equal<Contains<string, T1>, true>>,
15
+ // "bar" does NOT extend "foo"
16
+ Expect<Equal<Contains<"bar", T1>, false>>,
17
+ // T4 has literal string but this will match the wide type string
18
+ Expect<Equal<Contains<string, T4>, true>>,
19
+ // T1 has both wide and narrow versions of "number"
20
+ Expect<Equal<Contains<number, T1>, true>>,
21
+ // T3 has narrow versions of "number"
22
+ Expect<Equal<Contains<number, T3>, true>>,
23
+ // boolean literals evaluate to wide type
24
+ Expect<Equal<Contains<boolean, T2>, true>>
25
+ ];
26
+ const cases: cases = [true, true, true, true, true, true];
27
+ });
28
+ });
29
+
30
+ describe("NarrowlyContains<T,A>", () => {
31
+ it("happy-path", () => {
32
+ type T1 = [number, 32, 64, "foo"];
33
+ type T2 = [false, true];
34
+ type T3 = [42, 64, 128];
35
+ type T4 = ["foo", "bar"];
36
+
37
+ type cases = [
38
+ // "foo" is not equal to string
39
+ Expect<Equal<NarrowlyContains<string, T1>, false>>,
40
+ // "foo" does equal "foo"
41
+ Expect<Equal<NarrowlyContains<"foo", T1>, true>>,
42
+ // T4 has literal string but this doesn't match with NarrowlyContains
43
+ Expect<Equal<NarrowlyContains<string, T4>, false>>,
44
+ // T1 has both wide and narrow versions of "number" but match is only on wide type
45
+ Expect<Equal<NarrowlyContains<number, T1>, true>>,
46
+ // T3 has matches on narrow number
47
+ Expect<Equal<NarrowlyContains<42, T3>, true>>,
48
+ // T3 identifies a non-match of narrow numbers
49
+ Expect<Equal<NarrowlyContains<442, T3>, false>>,
50
+ // boolean literals evaluate to wide type
51
+ Expect<Equal<NarrowlyContains<boolean, T2>, false>>
52
+ ];
53
+ const cases: cases = [true, true, true, true, true, true, true];
54
+ });
55
+ });
@@ -1,6 +1,6 @@
1
1
  import { describe, it } from "vitest";
2
2
  import { Equal, Expect } from "@type-challenges/utils";
3
- import { TypeDefault } from "src/types/type-checks/TypeDefault";
3
+ import { TypeDefault } from "src/types/boolean-logic/TypeDefault";
4
4
  import { literal } from "src/runtime/literals";
5
5
 
6
6
  describe("TypeDefault<T,D>", () => {
@@ -0,0 +1,19 @@
1
+ import { Equal, Expect } from "@type-challenges/utils";
2
+ import { Length } from "src/types";
3
+ import { describe, it } from "vitest";
4
+
5
+ describe("Length<T>", () => {
6
+ it("happy-path", () => {
7
+ const a1 = [1, 2, 3] as const;
8
+ const a2 = [1, 2, 3, 4, 5, 6] as const;
9
+ type A1 = typeof a1;
10
+ type A2 = typeof a2;
11
+
12
+ type cases = [
13
+ //
14
+ Expect<Equal<Length<A1>, 3>>,
15
+ Expect<Equal<Length<A2>, 6>>
16
+ ];
17
+ const cases: cases = [true, true];
18
+ });
19
+ });
@@ -2,6 +2,8 @@ import { describe, expect, it } from "vitest";
2
2
 
3
3
  import type { Expect, Equal } from "@type-challenges/utils";
4
4
  import {
5
+ ifArray,
6
+ ifArrayPartial,
5
7
  ifBoolean,
6
8
  ifNumber,
7
9
  ifString,
@@ -9,9 +11,10 @@ import {
9
11
  ifUndefined,
10
12
  isTrue,
11
13
  } from "src/runtime/type-checks";
12
- import { EndsWith, StartsWith } from "src/types";
14
+ import { EndsWith, Extends, Or, StartsWith } from "src/types";
13
15
  import { ifStartsWith, startsWith } from "src/runtime/type-checks/startsWith";
14
16
  import { box } from "src/runtime/literals";
17
+ import { or } from "src/runtime";
15
18
 
16
19
  describe("runtime if/is", () => {
17
20
  it("ifString(v,i,e)", () => {
@@ -55,7 +58,7 @@ describe("runtime if/is", () => {
55
58
  type cases = [
56
59
  Expect<Equal<typeof t, 42>>, //
57
60
  Expect<Equal<typeof f, 42>>, //
58
- Expect<Equal<typeof f2, 42>> //
61
+ Expect<Equal<typeof f2, "yikes" | 42>> //
59
62
  ];
60
63
  const cases: cases = [true, true, true];
61
64
  });
@@ -115,6 +118,104 @@ describe("runtime if/is", () => {
115
118
  const cases: cases = [true, true];
116
119
  });
117
120
 
121
+ it("Or<T[]> type util", () => {
122
+ type T1 = Or<[true, true, false]>;
123
+ type T2 = Or<[false, false, false]>;
124
+ type T3 = Or<[boolean, boolean, true]>;
125
+ type T4 = Or<[boolean, boolean, boolean]>;
126
+
127
+ type cases = [
128
+ Expect<Equal<T1, true>>,
129
+ Expect<Equal<T2, false>>,
130
+ Expect<Equal<T3, true>>,
131
+ Expect<Equal<T4, boolean>>
132
+ ];
133
+ const cases: cases = [true, true, true, true];
134
+ });
135
+
136
+ it("or() runtime utility", () => {
137
+ const t1 = or(true, true, false);
138
+ const t2 = or(false, false, false);
139
+ const t3 = or(false as boolean, false, true);
140
+ const t4 = or(false as boolean, false as boolean, true as boolean);
141
+
142
+ type cases = [
143
+ Expect<Equal<typeof t1, true>>,
144
+ Expect<Equal<typeof t2, false>>,
145
+ Expect<Equal<typeof t3, true>>,
146
+ Expect<Equal<typeof t4, boolean>>
147
+ ];
148
+ const cases: cases = [true, true, true, true];
149
+
150
+ expect(t1).toBe(true);
151
+ expect(t2).toBe(false);
152
+ expect(t3).toBe(true);
153
+ expect(t4).toBe(true);
154
+ });
155
+
156
+ it("Extends<T,EXTENDS> with single clause", () => {
157
+ type cases = [
158
+ //
159
+ Expect<Equal<Extends<1, number>, true>>,
160
+ Expect<Equal<Extends<2, string>, false>>,
161
+ Expect<Equal<Extends<2, 2 | 3>, true>>
162
+ ];
163
+ const cases: cases = [true, true, true];
164
+ });
165
+
166
+ it("IfExtends<T,EXTENDS,IF,ELSE", () => {
167
+ type cases = [/** type tests */];
168
+ const cases: cases = [];
169
+ });
170
+
171
+ it("ifArray(val,if,else) utility", () => {
172
+ const fn0 = ifArray(
173
+ "foobar" as string,
174
+ (i) => `I'm an array, my length is ${i.length}` as const,
175
+ (i) => `I'm not an array, I am ${i}` as const
176
+ );
177
+ const fn1 = ifArray(
178
+ "foobar",
179
+ (i) => `I'm an array, my length is ${i.length}` as const,
180
+ (i) => `I'm not an array, I am ${i}` as const
181
+ );
182
+ const fn2 = ifArray(
183
+ ["foo", "bar"] as const,
184
+ (i) => `I'm an array, my length is ${i.length}` as const,
185
+ (i) => `I'm not an array, I am ${i}` as const
186
+ );
187
+
188
+ const fn3 = ifArray(
189
+ ["foo", "bar"],
190
+ (i) => `I'm an array, my length is ${i.length}` as const,
191
+ (i) => `I'm not an array, I am ${i}` as const
192
+ );
193
+
194
+ type cases = [
195
+ Expect<Equal<typeof fn0, `I'm not an array, I am ${string}`>>,
196
+ Expect<Equal<typeof fn1, `I'm not an array, I am foobar`>>,
197
+ Expect<Equal<typeof fn2, `I'm an array, my length is 2`>>,
198
+ Expect<Equal<typeof fn3, `I'm an array, my length is ${number}`>>
199
+ ];
200
+ const cases: cases = [true, true, true, true];
201
+ });
202
+
203
+ it("ifArrayPartial()()", () => {
204
+ const arrTest = ifArrayPartial<string | string[]>()(
205
+ (i) => `I'm an array, my length is ${i.length}`,
206
+ (i) => `I'm not an array, I am ${i}`
207
+ );
208
+
209
+ const t1 = arrTest("Bob");
210
+ const t2 = arrTest(["foo", "bar"]);
211
+
212
+ type cases = [
213
+ Expect<Equal<typeof t1, `I'm not an array, I am ${string}`>>,
214
+ Expect<Equal<typeof t2, `I'm an array, my length is ${number}`>>
215
+ ];
216
+ const cases: cases = [true, true];
217
+ });
218
+
118
219
  it("ifUndefined(v,i,e)", () => {
119
220
  const t = ifUndefined(undefined, 42, false);
120
221
  const f = ifUndefined(false, "yikes", 42);
@@ -1,16 +0,0 @@
1
- /**
2
- * **IsBooleanLiteral**
3
- *
4
- * Type utility which returns true/false if the boolean value is a _boolean literal_ versus
5
- * just the wider _boolean_ type.
6
- */
7
- export type IsBooleanLiteral<T extends boolean> = boolean extends T ? false : true;
8
-
9
- /**
10
- * **IfBooleanLiteral**
11
- *
12
- * Branch utility which returns `IF` type when `T` is a boolean literal and `ELSE` otherwise
13
- */
14
- export type IfBooleanLiteral<T extends boolean, IF, ELSE> = IsBooleanLiteral<T> extends true
15
- ? IF
16
- : ELSE;