inferred-types 0.33.0 → 0.33.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 (145) hide show
  1. package/.vscode/settings.json +1 -0
  2. package/dist/index.d.ts +1182 -1125
  3. package/dist/index.js +73 -182
  4. package/dist/index.mjs +70 -175
  5. package/package.json +16 -15
  6. package/src/{utility/errors → errors}/ReadOnlyViolation.ts +0 -0
  7. package/src/{utility/errors → errors}/index.ts +0 -0
  8. package/src/index.ts +1 -3
  9. package/src/{utility → runtime}/README.md +0 -0
  10. package/src/{utility → runtime}/api/api.ts +0 -0
  11. package/src/{utility → runtime}/api/index.ts +0 -0
  12. package/src/{utility/modelling → runtime/builders}/Model.ts +0 -0
  13. package/src/runtime/builders/url.ts +15 -0
  14. package/src/{utility/boolean-logic → runtime/combinators}/and.ts +0 -0
  15. package/src/{utility/boolean-logic → runtime/combinators}/filter.ts +0 -0
  16. package/src/{utility/boolean-logic → runtime/combinators}/index.ts +0 -0
  17. package/src/{utility/boolean-logic → runtime/combinators}/not.ts +0 -0
  18. package/src/{utility/boolean-logic → runtime/combinators}/or.ts +0 -0
  19. package/src/{utility → runtime}/createFnWithProps.ts +0 -0
  20. package/src/{utility → runtime}/dictionary/arrayToKeyLookup.ts +0 -0
  21. package/src/{utility → runtime}/dictionary/defineProperties.ts +0 -0
  22. package/src/{utility → runtime}/dictionary/dictArr.ts +0 -0
  23. package/src/{utility → runtime}/dictionary/dictionaryTransform.ts +0 -0
  24. package/src/{utility → runtime}/dictionary/entries.ts +0 -0
  25. package/src/{utility → runtime}/dictionary/index.ts +0 -0
  26. package/src/{utility → runtime}/dictionary/kv/dictToKv.ts +1 -1
  27. package/src/{utility → runtime}/dictionary/kv/filterDictArray.ts +1 -1
  28. package/src/{utility → runtime}/dictionary/kv/index.ts +0 -0
  29. package/src/{utility → runtime}/dictionary/kv/kv.ts +0 -0
  30. package/src/{utility → runtime}/dictionary/kv/kvToDict.ts +0 -0
  31. package/src/{utility → runtime}/dictionary/mapTo.ts +0 -0
  32. package/src/{utility → runtime}/dictionary/mapValues.ts +0 -0
  33. package/src/{utility → runtime}/dictionary/merge.ts +0 -0
  34. package/src/{utility → runtime}/dictionary/strArrayToDict.ts +0 -0
  35. package/src/{utility → runtime}/index.ts +1 -3
  36. package/src/{utility → runtime}/keys.ts +0 -0
  37. package/src/{utility → runtime}/lists/asArray.ts +0 -0
  38. package/src/{utility → runtime}/lists/groupBy.ts +0 -0
  39. package/src/{utility → runtime}/lists/index.ts +0 -0
  40. package/src/{utility → runtime}/literals/ExplicitFunction.ts +0 -0
  41. package/src/runtime/literals/Suggest.ts +19 -0
  42. package/src/{utility → runtime}/literals/arrayToObject.ts +0 -0
  43. package/src/runtime/literals/box.ts +77 -0
  44. package/src/{utility → runtime}/literals/defineType.ts +0 -0
  45. package/src/{utility → runtime}/literals/identity.ts +0 -0
  46. package/src/{utility → runtime}/literals/index.ts +2 -0
  47. package/src/{utility → runtime}/literals/literal.ts +0 -0
  48. package/src/{utility → runtime}/ruleset.ts +0 -0
  49. package/src/{utility → runtime}/runtime/README.md +0 -0
  50. package/src/{utility → runtime}/runtime/condition.ts +0 -0
  51. package/src/{utility → runtime}/runtime/index.ts +1 -2
  52. package/src/{utility → runtime}/runtime/type.ts +1 -1
  53. package/src/{utility → runtime}/runtime/withValue.ts +0 -0
  54. package/src/{utility → runtime}/state/Configurator.ts +0 -0
  55. package/src/{utility → runtime}/state/FluentConfigurator.ts +0 -0
  56. package/src/{utility → runtime}/state/index.ts +0 -0
  57. package/src/{utility/runtime → runtime/type-checks}/ifTypeOf.ts +0 -0
  58. package/src/{utility/runtime/conditions → runtime/type-checks}/index.ts +0 -0
  59. package/src/{utility/runtime/conditions → runtime/type-checks}/isArray.ts +0 -0
  60. package/src/{utility/runtime/conditions → runtime/type-checks}/isBoolean.ts +0 -0
  61. package/src/{utility/runtime/conditions → runtime/type-checks}/isFalse.ts +0 -0
  62. package/src/{utility/runtime/conditions → runtime/type-checks}/isFunction.ts +11 -2
  63. package/src/{utility/runtime/conditions → runtime/type-checks}/isNull.ts +0 -0
  64. package/src/{utility/runtime/conditions → runtime/type-checks}/isNumber.ts +0 -0
  65. package/src/{utility/runtime/conditions → runtime/type-checks}/isObject.ts +1 -1
  66. package/src/{utility/runtime/conditions → runtime/type-checks}/isString.ts +13 -5
  67. package/src/{utility/runtime/conditions → runtime/type-checks}/isSymbol.ts +0 -0
  68. package/src/{utility/runtime/conditions → runtime/type-checks}/isTrue.ts +1 -1
  69. package/src/{utility/runtime/conditions → runtime/type-checks}/isUndefined.ts +1 -1
  70. package/src/runtime/type-checks/startsWith.ts +109 -0
  71. package/src/{shared → runtime}/valueTypes.ts +0 -0
  72. package/src/types/FunctionType.ts +12 -2
  73. package/src/types/Mutable.ts +1 -1
  74. package/src/types/alphabetic/Url.ts +29 -0
  75. package/src/types/alphabetic/alpha-characters.ts +8 -0
  76. package/src/types/alphabetic/index.ts +1 -0
  77. package/src/types/dictionary/MapTo.ts +2 -2
  78. package/src/types/index.ts +2 -2
  79. package/src/types/lists/AfterFirst.ts +10 -0
  80. package/src/types/lists/First.ts +8 -0
  81. package/src/types/lists/FirstString.ts +4 -0
  82. package/src/types/lists/Split.ts +21 -0
  83. package/src/types/lists/index.ts +4 -0
  84. package/src/types/ruleset-types.ts +1 -1
  85. package/src/types/type-checks/EndsWith.ts +22 -0
  86. package/src/types/{TypeInfo → type-checks}/Extends.ts +0 -0
  87. package/src/types/{TypeInfo → type-checks}/Includes.ts +0 -0
  88. package/src/types/{TypeInfo → type-checks}/IsBooleanLiteral.ts +0 -0
  89. package/src/types/{TypeInfo → type-checks}/IsLiteral.ts +0 -0
  90. package/src/types/{TypeInfo → type-checks}/IsNumericLiteral.ts +0 -0
  91. package/src/types/{TypeInfo → type-checks}/IsScalar.ts +0 -0
  92. package/src/types/{TypeInfo → type-checks}/IsStringLiteral.ts +2 -4
  93. package/src/types/{TypeInfo → type-checks}/IsUndefined.ts +0 -0
  94. package/src/types/type-checks/StartsWith.ts +43 -0
  95. package/src/types/{TypeInfo → type-checks}/TypeDefault.ts +1 -1
  96. package/src/types/{TypeInfo → type-checks}/index.ts +3 -1
  97. package/src/types/{TypeInfo/IsObject.ts → type-checks/object.ts} +0 -0
  98. package/src/types/type-checks/string.ts +21 -0
  99. package/src/types/type-conversion/TupleToUnion.ts +1 -3
  100. package/tests/ExplicitFunction-spec.ts +1 -1
  101. package/tests/arrayToKeyLookup-spec.ts +1 -1
  102. package/tests/arrayToObject-spec.ts +1 -1
  103. package/tests/boolean-logic/boolean.spec.ts +1 -1
  104. package/tests/boolean-logic/filter.spec.ts +1 -1
  105. package/tests/defineType-spec.ts +1 -1
  106. package/tests/dictionary/Get.spec.ts +1 -1
  107. package/tests/dictionary/TypeDefault.test.ts +2 -2
  108. package/tests/dictionary/mapTo.test.ts +1 -1
  109. package/tests/dictionary/merge.test.ts +1 -1
  110. package/tests/dictionaryTransform-spec.ts +1 -1
  111. package/tests/ifTypeOf-spec.ts +3 -2
  112. package/tests/kv/dict-to-kv-and-back.spec.ts +2 -2
  113. package/tests/kv/entries-spec.ts +1 -1
  114. package/tests/kv/keys.spec.ts +1 -1
  115. package/tests/kv/kv-spec.ts +1 -1
  116. package/tests/lists/First.test.ts +43 -0
  117. package/tests/lists/Split.test.ts +29 -0
  118. package/tests/lists/asArray.test.ts +1 -1
  119. package/tests/lists/dictArr.test.ts +1 -1
  120. package/tests/literal-spec.ts +1 -1
  121. package/tests/{string-literals → literals}/AllCaps.spec.ts +0 -0
  122. package/tests/{string-literals → literals}/CamelCase.spec.ts +0 -0
  123. package/tests/{string-literals → literals}/Dasherize.spec.ts +0 -0
  124. package/tests/{string-literals → literals}/HasUppercase.spec.ts +0 -0
  125. package/tests/{string-literals → literals}/PascalCase.spec.ts +0 -0
  126. package/tests/{string-literals → literals}/SnakeCase.spec.ts +0 -0
  127. package/tests/literals/box.test.ts +77 -0
  128. package/tests/{string-literals → literals}/whitespace-capture.spec.ts +0 -0
  129. package/tests/mapValues-spec.ts +1 -1
  130. package/tests/runtime/condition.spec.ts +1 -1
  131. package/tests/runtime/if-is.spec.ts +158 -2
  132. package/tests/runtime/type.spec.ts +1 -1
  133. package/tests/strArrayToDict-spec.ts +1 -1
  134. package/tests/withValue.spec.ts +1 -1
  135. package/vitest.config.ts +2 -5
  136. package/src/Mutation/MutationFunction.ts +0 -26
  137. package/src/Mutation/MutationIdentity.ts +0 -36
  138. package/src/Mutation/index.ts +0 -14
  139. package/src/shared/README.md +0 -3
  140. package/src/shared/index.ts +0 -15
  141. package/src/shared/randomString.ts +0 -5
  142. package/src/shared/uuid.ts +0 -5
  143. package/src/types/First.ts +0 -4
  144. package/src/utility/modelling/index.ts +0 -12
  145. package/tests/MutationIdentity-spec.ts +0 -25
@@ -2,7 +2,7 @@ import { KvFrom } from "src/types/kv";
2
2
  import { Mutable } from "src/types/Mutable";
3
3
  import { Narrowable } from "src/types/Narrowable";
4
4
  import { UnionToTuple } from "src/types/type-conversion";
5
- import { keys } from "src/utility/keys";
5
+ import { keys } from "src/runtime/keys";
6
6
 
7
7
  /**
8
8
  * Converts a dictionary object into an array of dictionaries with `key` and `value` properties
@@ -1,5 +1,5 @@
1
1
  import { DictArray, DictArrayFilterCallback } from "src/types/tuples";
2
- import { Configurator, IConfigurator } from "src/utility/state";
2
+ import { Configurator, IConfigurator } from "src/runtime/state";
3
3
 
4
4
  export interface Array<T> {
5
5
  filter<U extends T>(pred: (a: T) => a is U): U[];
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -10,12 +10,10 @@ export * from "./keys";
10
10
  export * from "./ruleset";
11
11
  // directory exports
12
12
  export * from "./api/index";
13
- export * from "./boolean-logic/index";
13
+ export * from "./combinators/index";
14
14
  export * from "./dictionary/index";
15
- export * from "./errors/index";
16
15
  export * from "./lists/index";
17
16
  export * from "./literals/index";
18
- export * from "./modelling/index";
19
17
  export * from "./runtime/index";
20
18
  export * from "./state/index";
21
19
 
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,19 @@
1
+ /**
2
+ * **Suggest**
3
+ *
4
+ * Type utility that helps to build a enumerated set
5
+ * of string literals which _could_ be the value for
6
+ * a string based property but _allows_ a string that
7
+ * is not part of the suggestion to be typed in too.
8
+ */
9
+ export type Suggest<T extends string> = T | (string & {});
10
+
11
+ /**
12
+ * **SuggestNumeric**`<T>`
13
+ *
14
+ * Type utility that helps to build a enumerated set
15
+ * of numeric literals which _could_ be the value for
16
+ * a number based property but _allows_ a number that
17
+ * is not part of the suggestion to be typed in too.
18
+ */
19
+ export type SuggestNumeric<T extends number> = T | (number & {});
@@ -0,0 +1,77 @@
1
+ import { AfterFirst, Narrowable } from "src/types";
2
+ import { First } from "src/types/lists/First";
3
+
4
+ export interface Box<T> {
5
+ __kind: "box";
6
+ value: T;
7
+ /**
8
+ * Unbox the boxed value in the narrowest possible type.
9
+ *
10
+ * **Note:** _if you want a wider type definition use `wide()`
11
+ * instead._
12
+ */
13
+ unbox(): T;
14
+ // /**
15
+ // * If the boxed value is a function with generics then you have opportunity to
16
+ // * _narrow_ the type definition over time. This is achieved in a type strong manner,
17
+ // * so you can't change the fundamental type but this example will work as expected:
18
+ // * ```ts
19
+ // * const fn = <T extends string>(name: T) => `Hello ${name}` as const;
20
+ // * const b = box(fn);
21
+ // * // later
22
+ // * const b2 = b.narrow<"foo" | "bar">();
23
+ // * ```
24
+ // */
25
+ // narrow: NarrowBox<T>;
26
+ }
27
+
28
+ export type BoxValue<T extends Box<any>> = T extends Box<infer V> ? V : never;
29
+
30
+ export type BoxedFnParams<T extends Box<any>> = T extends Box<infer V>
31
+ ? V extends (...args: infer A) => any
32
+ ? A
33
+ : []
34
+ : [];
35
+
36
+ export type BoxedReturn<T extends Box<any>> = T extends Box<infer V>
37
+ ? V extends Function
38
+ ? ReturnType<T["value"]>
39
+ : T["value"]
40
+ : never;
41
+
42
+ export type NarrowBox<T> = <
43
+ N extends BoxedFnParams<Box<T>> | First<BoxedFnParams<Box<T>>>
44
+ >() => N extends BoxedFnParams<Box<T>>
45
+ ? T extends (...args: any[]) => any
46
+ ? (...args: N) => Box<T>["unbox"]
47
+ : never
48
+ : (first: N, ...rest: AfterFirst<BoxedFnParams<Box<T>>>) => BoxedReturn<Box<T>>;
49
+
50
+ /**
51
+ * Allows a value with an inner-type to be boxed into a dictionary
52
+ * so that this type inference is preserved with the help of
53
+ * [instantiation expressions](https://devblogs.microsoft.com/typescript/announcing-typescript-4-7-beta/#instantiation-expressions).
54
+ *
55
+ * NOTE: this feature is immature at best right now
56
+ */
57
+ export function box<T extends Narrowable>(value: T): Box<T> {
58
+ const rtn: Box<T> = {
59
+ __kind: "box",
60
+ value,
61
+ unbox: () => value,
62
+ };
63
+
64
+ return rtn;
65
+ }
66
+
67
+ export function isBox(thing: unknown): thing is Box<any> {
68
+ return (
69
+ typeof thing === "object" && "__kind" in (thing as object) && (thing as any).__kind === "box"
70
+ );
71
+ }
72
+
73
+ export type Unbox<T> = T extends Box<infer U> ? U : T;
74
+
75
+ export function unbox<T>(thing: T): Unbox<T> {
76
+ return isBox(thing) ? thing.unbox() : thing;
77
+ }
File without changes
File without changes
@@ -6,9 +6,11 @@
6
6
  // file exports
7
7
  export * from "./ExplicitFunction";
8
8
  export * from "./arrayToObject";
9
+ export * from "./box";
9
10
  export * from "./defineType";
10
11
  export * from "./identity";
11
12
  export * from "./literal";
13
+ export * from "./Suggest";
12
14
 
13
15
  // #endregion auto-indexed files
14
16
 
File without changes
File without changes
File without changes
File without changes
@@ -5,11 +5,10 @@
5
5
 
6
6
  // file exports
7
7
  export * from "./condition";
8
- export * from "./ifTypeOf";
9
8
  export * from "./type";
10
9
  export * from "./withValue";
11
10
  // directory exports
12
- export * from "./conditions/index";
11
+ export * from "../type-checks/index";
13
12
 
14
13
  // #endregion auto-indexed files
15
14
 
@@ -14,7 +14,7 @@ import {
14
14
  isObject,
15
15
  isArray,
16
16
  ObjectType,
17
- } from "./conditions";
17
+ } from "../type-checks";
18
18
  // import { isLiteral } from "./conditions/isLiteral";
19
19
 
20
20
  export type Type<T extends any, V extends Function> = {
File without changes
File without changes
File without changes
@@ -2,6 +2,15 @@ import { FunctionType } from "src/types/FunctionType";
2
2
 
3
3
  export type IsFunction<T> = T extends FunctionType ? true : false;
4
4
 
5
+ export type HybridFunction<TProps extends {}> = (<TArgs extends any[]>(...args: TArgs) => any) &
6
+ TProps;
7
+
8
+ export type SimpleFunction = <TArgs extends any[]>(...args: TArgs) => any;
9
+
10
+ export type AnyFunction<TProps extends {} | never = never> = TProps extends {}
11
+ ? HybridFunction<TProps>
12
+ : SimpleFunction;
13
+
5
14
  /**
6
15
  * Checks whether a passed in value is a function and ensures run-time and types
7
16
  * are consistent.
@@ -14,6 +23,6 @@ export type IsFunction<T> = T extends FunctionType ? true : false;
14
23
  * encountered but if that function also has object types defined then the type will be a big
15
24
  * and ugly union type. This function will give you a proper boolean value in both cases.
16
25
  */
17
- export function isFunction<T extends unknown>(input: T): IsFunction<T> {
18
- return (typeof input === "function") as IsFunction<T>;
26
+ export function isFunction<T>(input: T): IsFunction<T> {
27
+ return (typeof input === "function" ? true : false) as IsFunction<T>;
19
28
  }
@@ -1,5 +1,5 @@
1
1
  import { FunctionType, Narrowable, Not } from "src/types";
2
- import { IsObject } from "src/types/TypeInfo";
2
+ import { IsObject } from "src/types/type-checks";
3
3
 
4
4
  export type ObjectType = Not<Record<string, Narrowable>, FunctionType>;
5
5
 
@@ -1,7 +1,15 @@
1
- import { Narrowable } from "src/types";
2
-
3
- export type IsString<T> = T extends string ? true : false;
1
+ import { Narrowable } from "src/types/Narrowable";
2
+ import { IfString, IsString } from "src/types/type-checks/string";
4
3
 
4
+ /**
5
+ * **isString**
6
+ *
7
+ * Returns true or false on whether the passed in parameter is a
8
+ * string (either a wide string or a string literal).
9
+ *
10
+ * The boolean return is traceable by the type system as well as the
11
+ * runtime system.
12
+ */
5
13
  export function isString<T>(i: T) {
6
14
  return (typeof i === "string") as IsString<T>;
7
15
  }
@@ -13,7 +21,7 @@ export function isString<T>(i: T) {
13
21
  * a _string_ and returns one of two values (strongly typed) based on the evaluation
14
22
  * of this criteria.
15
23
  *
16
- * @param val the value being tested
24
+ * @param val the value being tested for being a string
17
25
  * @param ifVal the value (strongly typed) returned if val is _string_
18
26
  * @param elseVal the value (strongly typed) returned if val is NOT a _string
19
27
  */
@@ -22,5 +30,5 @@ export function ifString<T extends Narrowable, IF extends Narrowable, ELSE exten
22
30
  ifVal: IF,
23
31
  elseVal: ELSE
24
32
  ) {
25
- return (isString(val) ? ifVal : elseVal) as IsString<T> extends true ? IF : ELSE;
33
+ return (isString(val) ? ifVal : elseVal) as IfString<T, IF, ELSE>;
26
34
  }
@@ -42,6 +42,6 @@ export function isTrue<T extends Narrowable>(i: T) {
42
42
  * @param ifVal the value (strongly typed) returned if val is _true_ value
43
43
  * @param elseVal the value (strongly typed) returned if val is NOT a _true_ value
44
44
  */
45
- export function ifTrue<T, IF, ELSE>(val: T, ifVal: IF, elseVal: ELSE) {
45
+ export function ifTrue<T extends Narrowable, IF, ELSE>(val: T, ifVal: IF, elseVal: ELSE) {
46
46
  return (isTrue(val) ? ifVal : elseVal) as IsTrue<T> extends true ? IF : ELSE;
47
47
  }
@@ -1,5 +1,5 @@
1
1
  import { Narrowable } from "src/types";
2
- import { IsUndefined } from "src/types/TypeInfo/IsUndefined";
2
+ import { IsUndefined } from "src/types/type-checks/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;
@@ -0,0 +1,109 @@
1
+ import { IfStartsWith, StartsWith } from "src/types/type-checks";
2
+ import { IfUndefined } from "src/types/type-checks/IsUndefined";
3
+ import { createFnWithProps } from "../createFnWithProps";
4
+ import { box, Box } from "../literals";
5
+ import { ifTrue } from "./isTrue";
6
+
7
+ /**
8
+ * **startsWith**
9
+ *
10
+ * A higher-order and type strong way to checking whether a string literal `<T>` starts with
11
+ * another known string literal `<S>`:
12
+ * ```ts
13
+ * const answer = startsWith("foo")("foobar");
14
+ * ```
15
+ */
16
+ export const startsWith =
17
+ <S extends string>(
18
+ /** The starting string you will test for */
19
+ start: S
20
+ ) =>
21
+ <T extends string>(
22
+ /** The text being tested */
23
+ input: T
24
+ ): StartsWith<T, S> => {
25
+ return input.startsWith(start) as StartsWith<T, S>;
26
+ };
27
+
28
+ /**
29
+ * **IfStartsWithFn**
30
+ *
31
+ * A function which comes from a partial application of the `ifStartsWith()`
32
+ * utility. This type will receive a value `<T>` and _if_ this values starts
33
+ * with `<S>` then the callback function will executed in a type strong manner.
34
+ */
35
+ export type IfStartsWith__Fn<
36
+ /** The "start with" constraint */
37
+ TStartsWith extends string,
38
+ TIf extends Box<<T extends string>(i: `${TStartsWith}${T}`) => any>,
39
+ TElse extends Box<(<T extends string>(i: T) => any) | undefined>
40
+ > = <T extends string>(
41
+ val: T
42
+ ) => IfStartsWith<
43
+ T, //
44
+ TStartsWith,
45
+ // Condition Passes
46
+ ReturnType<TIf["value"]>,
47
+ // Condition Fails
48
+ IfUndefined<
49
+ TElse, //
50
+ undefined,
51
+ Exclude<TElse, undefined>
52
+ >
53
+ >;
54
+
55
+ export type NarrowFn<N extends string> = <F extends <T extends string>(input: T) => any>(
56
+ fn: F
57
+ ) => (input: N) => Box<F>["unbox"];
58
+
59
+ export const stringLiteralFn = <F extends <T extends string>(input: T) => any>(fn: F) => {
60
+ const b = box(fn);
61
+ const api = {
62
+ narrow<N extends string>() {
63
+ return (input: N) => b.unbox()(input);
64
+ },
65
+ };
66
+
67
+ return createFnWithProps(fn, api);
68
+ };
69
+
70
+ export type StringLiteralFn<S extends string = string> = <T extends S>(input: T) => any;
71
+
72
+ /**
73
+ * **ifStartsWith**
74
+ *
75
+ * Type strong way to move into a conditional execution block:
76
+ * ```ts
77
+ * // partial application
78
+ * const mutate = ifStartsWith(
79
+ * "foo",
80
+ * i => `${i} is a foo`,
81
+ * i => `${i} ain't welcome in this town`
82
+ * );
83
+ * // type: `foobar is a foo`
84
+ * const outcome = mutate("foobar");
85
+ * ```
86
+ *
87
+ * Where the variable `i` will _extend_ a string and function which this utility
88
+ * returns is able to
89
+ */
90
+ 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
+ >(
96
+ /** the string literal _start value_ which a string must begin with */
97
+ start: TStartsWith,
98
+ /** a mutation function when a value _does_ start with `TStartsWith` */
99
+ isTrue: TIf,
100
+ /** an optional mutation function */
101
+ isFalse: TElse
102
+ ) =>
103
+ <I extends string>(input: I) =>
104
+ ifTrue(
105
+ // condition
106
+ startsWith(start)(input),
107
+ isTrue(input),
108
+ isFalse(input)
109
+ ) as IfStartsWith<I, TStartsWith, ReturnType<TIf>, ReturnType<TElse>>;
File without changes
@@ -1,9 +1,19 @@
1
1
  /**
2
- * Defines a function type.
2
+ * **FunctionType**
3
+ *
4
+ * Provides a way to correctly match for regular functions _and_ functions which
5
+ * also have a dictionary hash alongside the root function.
3
6
  *
4
7
  * - without the generic `T` specified it simply matches correctly on both plain functions as well as functions which also have properties on them (this is consistent to how runtime's `typeof` operator works)
5
8
  * - with the generic you can specify the shape of the key/values
6
9
  */
7
10
  export type FunctionType<T extends {} = {}> = {} extends T
8
11
  ? Function | (Function & { [key: string]: any })
9
- : Function | (Function & T);
12
+ : Function | (Function & T);
13
+
14
+ /**
15
+ * **FnShape**
16
+ *
17
+ * Simple way to express the shape of a function's arguments and return type.
18
+ */
19
+ export type FnShape<A extends any[] = any[], R extends any = any> = (...args: A) => R;
@@ -1,4 +1,4 @@
1
- import { IsObject } from "./TypeInfo";
1
+ import { IsObject } from "./type-checks";
2
2
 
3
3
  /**
4
4
  * Makes a readonly structure mutable
@@ -0,0 +1,29 @@
1
+ import { AlphaNumeric, Ipv4, VariableName } from "./alpha-characters";
2
+
3
+ export type NetworkProtocol = "http" | "https" | "file" | "ws" | "wss";
4
+
5
+ /**
6
+ * A literal variant of _string_ which is meant to represent a domain name
7
+ * (e.g., `www.someplace.com`, etc.)
8
+ */
9
+ export type DomainName =
10
+ | `${AlphaNumeric}${string}.${AlphaNumeric}${string}`
11
+ | `${AlphaNumeric}${string}.${AlphaNumeric}${string}.${string}`
12
+ | `${AlphaNumeric}${string}.${AlphaNumeric}${string}.${string}.${string}`;
13
+
14
+ export type RelativeUrl = `${VariableName | "/"}`;
15
+
16
+ /**
17
+ * A literal variant of _string_ which forces a string to follow conventions
18
+ * for a fully qualified URL like `https://google.com`. It can't ensure the
19
+ * type is fully valid but does help to avoid some typos.
20
+ */
21
+ export type FullyQualifiedUrl = `${NetworkProtocol}://${Ipv4 | DomainName}/${string}`;
22
+
23
+ export type UrlBuilder =
24
+ | (<P extends NetworkProtocol, D extends DomainName, B extends RelativeUrl>(
25
+ protocol: P,
26
+ domain: D,
27
+ basePath: B
28
+ ) => `${P}://${D}/${B}`)
29
+ | (<U extends RelativeUrl>(url: U) => U);
@@ -65,9 +65,17 @@ export type NumericString = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8"
65
65
  */
66
66
  export type AlphaNumeric = Alpha | NumericString;
67
67
 
68
+ /**
69
+ * Allows alphanumeric characters and some special characters typically allowed
70
+ * in variable names.
71
+ */
72
+ export type VariableName = AlphaNumeric | "_" | "." | "-";
73
+
68
74
  export type SpecialCharacters = "@" | "~" | "^" | "#" | "&" | "*";
69
75
 
70
76
  /**
71
77
  * Non-alphabetic characters including whitespace, string numerals, and
72
78
  */
73
79
  export type NonAlpha = Whitespace | Punctuation | NumericString | Bracket | SpecialCharacters;
80
+
81
+ export type Ipv4 = `${number}.${number}.${number}.${number}`;
@@ -19,6 +19,7 @@ export * from "./PascalCase";
19
19
  export * from "./Pluralize";
20
20
  export * from "./SnakeCase";
21
21
  export * from "./alpha-characters";
22
+ export * from "./Url";
22
23
 
23
24
  // #endregion auto-indexed files
24
25
 
@@ -4,9 +4,9 @@ import {
4
4
  DefaultManyToOneMapping,
5
5
  DefaultOneToManyMapping,
6
6
  DefaultOneToOneMapping,
7
- } from "src/utility/dictionary/mapTo";
7
+ } from "src/runtime/dictionary/mapTo";
8
8
  import { EnumValues } from "../EnumValues";
9
- import { TypeDefault } from "../TypeInfo/TypeDefault";
9
+ import { TypeDefault } from "../type-checks/TypeDefault";
10
10
 
11
11
  /**
12
12
  * Expresses relationship between inputs/outputs:
@@ -8,7 +8,7 @@ export * from "./Api";
8
8
  export * from "./Constructor";
9
9
  export * from "./EnumValues";
10
10
  export * from "./ExpandRecursively";
11
- export * from "./First";
11
+ export * from "./lists/First";
12
12
  export * from "./FunctionType";
13
13
  export * from "./If";
14
14
  export * from "./Include";
@@ -41,7 +41,7 @@ export * from "./literal-unions/index";
41
41
  export * from "./string-literals/index";
42
42
  export * from "./tuples/index";
43
43
  export * from "./type-conversion/index";
44
- export * from "./TypeInfo/index";
44
+ export * from "./type-checks/index";
45
45
 
46
46
  // #endregion auto-indexed files
47
47
 
@@ -0,0 +1,10 @@
1
+ /**
2
+ * **AfterFirst**`<T>`
3
+ *
4
+ * returns the elements in an array _after_ the first element
5
+ */
6
+ export type AfterFirst<T extends readonly any[]> = T extends readonly [any, ...any[]]
7
+ ? T extends readonly [any, ...infer Rest]
8
+ ? Rest
9
+ : never
10
+ : T;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Returns the first values type in an array of values
3
+ */
4
+ export type First<T extends readonly any[]> = T[0] extends T[number] ? T[0] : never;
5
+
6
+ export type FirstOrUndefined<T extends unknown> = T extends [unknown, ...[unknown]]
7
+ ? First<T>
8
+ : undefined;
@@ -0,0 +1,4 @@
1
+ /**
2
+ * returns the first `string` value from an array of values
3
+ */
4
+ export type FirstString<T> = T extends [infer S extends string, ...unknown[]] ? S : never;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * **Split**`<T, SEP>`
3
+ *
4
+ * Splits a string literal `T` by string literal _separator_ `SEP`. The result is an array
5
+ * of string literals.
6
+ */
7
+ export type Split<
8
+ T extends string,
9
+ SEP extends string,
10
+ ANSWER extends string[] = []
11
+ > = string extends T
12
+ ? // wide string so we can only return wide string[]
13
+ string[]
14
+ : T extends SEP
15
+ ? // the string === separator results in empty array
16
+ ANSWER
17
+ : // test whether can recurse
18
+ T extends `${infer HEAD}${SEP}${infer TAIL}`
19
+ ? // recurse to produce strong literal type
20
+ Split<TAIL, SEP, [...ANSWER, HEAD]>
21
+ : [...ANSWER, T];
@@ -5,6 +5,10 @@
5
5
  // hash-code: 582c0cf0
6
6
 
7
7
  // file exports
8
+ export * from "./AfterFirst";
9
+ export * from "./First";
10
+ export * from "./FirstString";
11
+ export * from "./Split";
8
12
  export * from "./UniqueForProp";
9
13
 
10
14
  // #endregion auto-indexed files
@@ -1,4 +1,4 @@
1
- import { TypeCondition } from "src/utility/runtime";
1
+ import { TypeCondition } from "src/runtime/type-checks/ifTypeOf";
2
2
  import { OptionalKeys } from "./dictionary/props";
3
3
  import { SameKeys } from "./dictionary/SameKeys";
4
4