inferred-types 0.35.0 → 0.36.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.
- package/README.md +2 -34
- package/dist/index.d.ts +1803 -1663
- package/dist/index.mjs +95 -26
- package/package.json +12 -11
- package/src/runtime/combinators/filter.ts +0 -1
- package/src/runtime/lists/asArray.ts +8 -4
- package/src/runtime/lists/createConverter.ts +62 -0
- package/src/runtime/lists/index.ts +1 -0
- package/src/runtime/literals/box.ts +41 -20
- package/src/runtime/literals/ensureLeading.ts +17 -0
- package/src/runtime/literals/ensureTrailing.ts +17 -0
- package/src/runtime/literals/index.ts +4 -2
- package/src/runtime/literals/pathJoin.ts +22 -7
- package/src/runtime/literals/{stripStarting.ts → stripLeading.ts} +4 -4
- package/src/runtime/literals/stripTrailing.ts +15 -0
- package/src/runtime/literals/wide.ts +13 -0
- package/src/runtime/type-checks/ifSameType.ts +20 -0
- package/src/runtime/type-checks/index.ts +1 -0
- package/src/runtime/type-checks/isBoolean.ts +2 -1
- package/src/runtime/type-checks/isFunction.ts +2 -4
- package/src/runtime/type-checks/isObject.ts +10 -2
- package/src/runtime/type-checks/isString.ts +1 -1
- package/src/runtime/type-checks/isUndefined.ts +8 -0
- package/src/types/alphabetic/EnsureLeading.ts +24 -0
- package/src/types/alphabetic/EnsureTrailing.ts +24 -0
- package/src/types/alphabetic/PathJoin.ts +43 -31
- package/src/types/alphabetic/{StripStarting.ts → StripLeading.ts} +1 -1
- package/src/types/alphabetic/{StripEnding.ts → StripTrailing.ts} +1 -1
- package/src/types/alphabetic/index.ts +4 -2
- package/src/types/boolean-logic/HasParameters.ts +21 -0
- package/src/types/boolean-logic/array.ts +2 -2
- package/src/types/boolean-logic/boolean.ts +1 -1
- package/src/types/boolean-logic/equivalency.ts +2 -2
- package/src/types/boolean-logic/index.ts +1 -0
- package/src/types/dictionary/props.ts +5 -0
- package/src/types/lists/ConvertAndMap.ts +151 -0
- package/src/types/type-conversion/Widen.ts +15 -0
- package/tests/boolean-logic/HasParameters.ts +29 -0
- package/tests/lists/asArray.test.ts +19 -1
- package/tests/literals/EnsureStripLeadingTrailing.test.ts +79 -0
- package/tests/literals/PathJoin.test.ts +44 -37
- package/tests/literals/box.test.ts +31 -23
- package/tests/runtime/if-is.spec.ts +66 -5
- package/tests/runtime/map-and-convert.test.ts +31 -0
- package/dist/index.js +0 -868
- package/src/runtime/literals/stripEnding.ts +0 -9
package/dist/index.d.ts
CHANGED
|
@@ -146,13 +146,13 @@ type Length<T extends readonly any[]> = T["length"];
|
|
|
146
146
|
*
|
|
147
147
|
* Type utility which tests whether two types -- `X` and `Y` -- are exactly the same type
|
|
148
148
|
*/
|
|
149
|
-
type
|
|
149
|
+
type IsEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
|
|
150
150
|
/**
|
|
151
151
|
* **NotEqual**`<X,Y>`
|
|
152
152
|
*
|
|
153
153
|
* Type utility which tests whether two types -- `X` and `Y` -- are _not_ exactly the same type
|
|
154
154
|
*/
|
|
155
|
-
type NotEqual<X, Y> = true extends
|
|
155
|
+
type NotEqual<X, Y> = true extends IsEqual<X, Y> ? false : true;
|
|
156
156
|
|
|
157
157
|
/**
|
|
158
158
|
* **AfterFirst**`<T>`
|
|
@@ -243,7 +243,7 @@ type Contains<T extends Narrowable, A extends readonly any[]> = First<A> extends
|
|
|
243
243
|
* `true` if `T` _extends_ any element in `A` making it match widely against `A`. If you
|
|
244
244
|
* prefer a wider match you can use `Contains<T,A>` instead.
|
|
245
245
|
*/
|
|
246
|
-
type NarrowlyContains<T extends Narrowable, A extends readonly any[]> =
|
|
246
|
+
type NarrowlyContains<T extends Narrowable, A extends readonly any[]> = IsEqual<First<A>, T> extends true ? true : [] extends AfterFirst<A> ? false : NarrowlyContains<T, AfterFirst<A>>;
|
|
247
247
|
|
|
248
248
|
/**
|
|
249
249
|
* Converts a Tuple type into a _union_ of the tuple elements
|
|
@@ -270,159 +270,191 @@ type LastInUnion<U> = UnionToIntersection<U extends unknown ? (x: U) => 0 : neve
|
|
|
270
270
|
*/
|
|
271
271
|
type UnionToTuple<U, Last = LastInUnion<U>> = [U] extends [never] ? [] : [...UnionToTuple<Exclude<U, Last>>, Last];
|
|
272
272
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
type IsBoolean<T> = T extends boolean ? true : false;
|
|
273
|
+
declare function createFnWithProps<F extends Function, P extends {}>(fn: F, props: P): F & P;
|
|
276
274
|
/**
|
|
277
|
-
*
|
|
278
|
-
* whether the type holds the narrow "true" type.
|
|
279
|
-
* ```ts
|
|
280
|
-
* // true
|
|
281
|
-
* type T = IsTrue<true>;
|
|
282
|
-
* // boolean
|
|
283
|
-
* type U = IsTrue<boolean>;
|
|
284
|
-
* // false
|
|
285
|
-
* type F = IsTrue<false>;
|
|
286
|
-
* type F2 = IsTrue<"false">;
|
|
287
|
-
* ```
|
|
275
|
+
* Adds a dictionary of key/value pairs to a function.
|
|
288
276
|
*/
|
|
289
|
-
|
|
290
|
-
type IsFalse<T extends Narrowable> = IsBoolean<T> extends true ? T extends false ? true : true extends T ? false : unknown : false;
|
|
277
|
+
declare function fnWithProps<A extends any[], R extends any, P extends {}>(fn: ((...args: A) => R), props: P): ((...args: A) => R) & P;
|
|
291
278
|
/**
|
|
292
|
-
*
|
|
293
|
-
* to the IF, ELSE, or MAYBE generic types passed in where _maybe_ is when T
|
|
294
|
-
* is the wide type of `boolean`
|
|
279
|
+
* Adds read-only (and narrowly typed) key/value pairs to a function
|
|
295
280
|
*/
|
|
296
|
-
|
|
281
|
+
declare function readonlyFnWithProps<A extends any[], R extends any, N extends Narrowable, P extends Record<keyof P, N>>(fn: ((...args: A) => R), props: P): ((...args: A) => R) & Readonly<P>;
|
|
282
|
+
|
|
297
283
|
/**
|
|
298
|
-
*
|
|
299
|
-
* to the IF, ELSE, or MAYBE generic types passed in where _maybe_ is when T
|
|
300
|
-
* is the wide type of `boolean`
|
|
284
|
+
* Provides the _keys_ of an object with the `keyof T` made explicit.
|
|
301
285
|
*/
|
|
302
|
-
|
|
286
|
+
declare function keys<T extends {}, W extends readonly string[]>(obj: T, ...without: W): Length<W> extends 0 ? (keyof T)[] : Exclude<keyof T, Keys<W, undefined>>[];
|
|
287
|
+
|
|
303
288
|
/**
|
|
304
|
-
* **
|
|
289
|
+
* **ruleSet**
|
|
305
290
|
*
|
|
306
|
-
*
|
|
307
|
-
* just the wider _boolean_ type.
|
|
308
|
-
*/
|
|
309
|
-
type IsBooleanLiteral<T extends Narrowable> = IsTrue<T> extends true ? true : IsFalse<T> extends true ? true : false;
|
|
310
|
-
/**
|
|
311
|
-
* **IfBooleanLiteral**
|
|
291
|
+
* Defines a ruleset composed of _dynamic_ and _static_ boolean operators.
|
|
312
292
|
*
|
|
313
|
-
*
|
|
293
|
+
* - the first function call defines _dynamic_ props (_optional_)
|
|
294
|
+
* - the second function call defines static values
|
|
295
|
+
*
|
|
296
|
+
* ```ts
|
|
297
|
+
* const rs = ruleSet(
|
|
298
|
+
* r => r.state()( { maybe: r => r.extends({ foo: 1 }) })
|
|
299
|
+
* )(
|
|
300
|
+
* { color: true, age: false }
|
|
301
|
+
* );
|
|
302
|
+
* ```
|
|
314
303
|
*/
|
|
315
|
-
|
|
304
|
+
declare function ruleSet<N extends Narrowable, TState extends Record<keyof TState, N>>(defn?: TState): TState | undefined;
|
|
305
|
+
|
|
306
|
+
declare const api: <N extends Narrowable, TPrivate extends Readonly<Record<any, N>>>(priv: TPrivate) => <TPublic extends object>(pub: TPublic) => () => TPublic;
|
|
316
307
|
|
|
317
308
|
/**
|
|
318
|
-
*
|
|
309
|
+
* A type utility which looks at a chain for functions and reduces the type
|
|
310
|
+
* to the final `ReturnType` of the chain.
|
|
319
311
|
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
312
|
+
* ```ts
|
|
313
|
+
* // number
|
|
314
|
+
* type T = FinalReturn<() => (foo: string) => (bar: string) => () => number>;
|
|
315
|
+
* ```
|
|
322
316
|
*/
|
|
323
|
-
type
|
|
317
|
+
type FinalReturn<T extends any> = T extends (...args: any[]) => any ? FinalReturn<ReturnType<T>> : T;
|
|
318
|
+
|
|
324
319
|
/**
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
* Branch utility which returns `IF` type when `T` is a string literal and `ELSE` otherwise
|
|
320
|
+
* A function which returns a boolean value
|
|
328
321
|
*/
|
|
329
|
-
type
|
|
330
|
-
|
|
331
|
-
] extends [true] ? IF : ELSE;
|
|
322
|
+
type LogicFunction<T extends readonly any[]> = (...args: T) => boolean;
|
|
323
|
+
|
|
332
324
|
/**
|
|
333
|
-
*
|
|
325
|
+
* Groups a number of "logic functions" together by combining their results using
|
|
326
|
+
* the logical **AND** operator.
|
|
334
327
|
*
|
|
335
|
-
*
|
|
336
|
-
* just the _number_ type.
|
|
328
|
+
* **Note:** a "logic function" is any function which returns a boolean
|
|
337
329
|
*/
|
|
338
|
-
|
|
330
|
+
declare const and: <T extends any[]>(...ops: readonly LogicFunction<T>[]) => LogicFunction<T>;
|
|
331
|
+
|
|
339
332
|
/**
|
|
340
|
-
* **
|
|
333
|
+
* **Or**`<T>`
|
|
341
334
|
*
|
|
342
|
-
*
|
|
335
|
+
* Takes an array of boolean values and produces a boolean OR across these values
|
|
343
336
|
*/
|
|
344
|
-
type
|
|
337
|
+
type Or<T extends readonly boolean[]> = NarrowlyContains<true, T> extends true ? true : NarrowlyContains<boolean, T> extends true ? boolean : false;
|
|
338
|
+
|
|
339
|
+
declare function or<O extends readonly boolean[]>(...conditions: O): Or<O>;
|
|
340
|
+
|
|
345
341
|
/**
|
|
346
|
-
*
|
|
342
|
+
* Groups a number of "logic functions" together by combining their results using
|
|
343
|
+
* the logical **NOT** operator.
|
|
347
344
|
*
|
|
348
|
-
*
|
|
349
|
-
* string, number, or boolean -- is a _literal_ value of that type (true) or
|
|
350
|
-
* the more generic wide type (false).
|
|
345
|
+
* **Note:** a "logic function" is any function which returns a boolean
|
|
351
346
|
*/
|
|
352
|
-
|
|
347
|
+
declare const not: <T extends any[]>(op: LogicFunction<T>) => LogicFunction<T>;
|
|
348
|
+
|
|
349
|
+
type FilterStarts = {
|
|
350
|
+
/** one or more string which the value is allowed to start with */
|
|
351
|
+
startsWith: string | string[];
|
|
352
|
+
};
|
|
353
|
+
type FilterIs = {
|
|
354
|
+
/** whether a string _**is**_ of a particular value */
|
|
355
|
+
is: string | string[];
|
|
356
|
+
};
|
|
357
|
+
type FilterEnds = {
|
|
358
|
+
endsWith: string | string[];
|
|
359
|
+
};
|
|
360
|
+
type FilterContains = {
|
|
361
|
+
/** whether any of the strings specified are _contained_ in the value */
|
|
362
|
+
contains: string | string[];
|
|
363
|
+
};
|
|
364
|
+
type FilterEquals = {
|
|
365
|
+
/** one or more values which _equal_ the value passed in */
|
|
366
|
+
equals: number | number[];
|
|
367
|
+
};
|
|
368
|
+
type FilterNotEqual = {
|
|
369
|
+
/** one or more values which ALL _do not equal_ the value passed in */
|
|
370
|
+
notEqual: number | number[];
|
|
371
|
+
};
|
|
372
|
+
type FilterGreaterThan = {
|
|
373
|
+
/** the incoming value is greater than this value */
|
|
374
|
+
greaterThan: number;
|
|
375
|
+
};
|
|
376
|
+
type FilterLessThan = {
|
|
377
|
+
/** the incoming value is less than this value */
|
|
378
|
+
lessThan: number;
|
|
379
|
+
};
|
|
380
|
+
type StringFilter = FilterIs | FilterStarts | FilterEnds | FilterContains | (FilterStarts & FilterEnds) | (FilterStarts & FilterContains) | (FilterEnds & FilterContains) | (FilterStarts & FilterEnds & FilterContains);
|
|
381
|
+
type NumericFilter = FilterEquals | FilterNotEqual | FilterGreaterThan | FilterLessThan | (FilterEquals & FilterNotEqual) | (FilterEquals & FilterGreaterThan) | (FilterEquals & FilterLessThan) | (FilterNotEqual & FilterGreaterThan) | (FilterNotEqual & FilterLessThan) | (FilterGreaterThan & FilterLessThan) | (FilterEquals & FilterGreaterThan & FilterLessThan) | (FilterNotEqual & FilterGreaterThan & FilterLessThan) | (FilterEquals & FilterNotEqual & FilterGreaterThan & FilterLessThan);
|
|
382
|
+
type FilterDefn = StringFilter | NumericFilter;
|
|
383
|
+
type NotFilter = {
|
|
384
|
+
/**
|
|
385
|
+
* **not**
|
|
386
|
+
*
|
|
387
|
+
* If you want to build a filter who's conditions being met results in _filtering_
|
|
388
|
+
* the value rather than accepting it then choose this.
|
|
389
|
+
*/
|
|
390
|
+
not: FilterDefn;
|
|
391
|
+
};
|
|
392
|
+
declare function isNotFilter(f: FilterDefn | NotFilter): f is NotFilter;
|
|
393
|
+
type UnwrapNot<T extends FilterDefn | NotFilter> = T extends NotFilter ? T["not"] extends StringFilter ? StringFilter : NumericFilter : T;
|
|
394
|
+
declare function isNumericFilter(filter: FilterDefn): filter is NumericFilter;
|
|
395
|
+
type UndefinedValue<U extends boolean> = true extends U ? "undefined treated as 'true'" : U extends "no-impact" ? "undefined treated in no-impact fashion" : "undefined treated as 'false'";
|
|
396
|
+
type UndefinedTreatment = "undefined treated as 'true'" | "undefined treated as 'false'";
|
|
397
|
+
type LogicalCombinator = "AND" | "OR";
|
|
353
398
|
/**
|
|
354
|
-
* **
|
|
355
|
-
*
|
|
356
|
-
* Type utility which returns true/false if the value passed -- a form of a
|
|
357
|
-
* string, number, or boolean -- is a _literal_ value of that type (true) or
|
|
358
|
-
* the more generic wide type (false).
|
|
399
|
+
* **FilterFn**
|
|
359
400
|
*
|
|
360
|
-
*
|
|
361
|
-
*
|
|
362
|
-
*
|
|
401
|
+
* A filter function derived from the `filter()` configurator. This function is intended to provide a type-strong _filter_ function which can be used like so:
|
|
402
|
+
* be used like:
|
|
403
|
+
* ```ts
|
|
404
|
+
* const onlyPrivate = filter({ startsWith: "_" });
|
|
405
|
+
* const privateFiles = files.filter(onlyPrivate);
|
|
406
|
+
* ```
|
|
363
407
|
*/
|
|
364
|
-
type
|
|
408
|
+
type FilterFn<T extends StringFilter | NumericFilter> = T extends StringFilter ? <V extends string | undefined>(input: V) => boolean : <V extends number | undefined>(input: V) => boolean;
|
|
365
409
|
/**
|
|
366
|
-
*
|
|
367
|
-
*
|
|
368
|
-
* Branch type utility with return `IF` when `T` is a _literal_ value and `ELSE` otherwise
|
|
410
|
+
* Defines a logical function for each condition type
|
|
369
411
|
*/
|
|
370
|
-
type
|
|
412
|
+
type ConditionFilter<T extends StringFilter | NumericFilter> = T extends StringFilter ? (input: string) => boolean : (input: number) => boolean;
|
|
371
413
|
/**
|
|
372
|
-
* **
|
|
414
|
+
* **filter**
|
|
373
415
|
*
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
*/
|
|
377
|
-
type IfOptionalLiteral<T, IF extends Narrowable, ELSE extends Narrowable> = IsOptionalLiteral<T> extends true ? IF : ELSE;
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* **Includes**`<TSource, TValue>`
|
|
416
|
+
* A higher order helper utility which builds a boolean _filter_ function based on a simple
|
|
417
|
+
* configuration object. Support either _string_ or _numeric_ filters.
|
|
381
418
|
*
|
|
382
|
-
*
|
|
383
|
-
*
|
|
419
|
+
* ```ts
|
|
420
|
+
* const str = filter({startsWith: ["_", "."], endsWith: ".md"});
|
|
421
|
+
* const num = filter({ greaterThan: 55, notEqual: [66, 77]});
|
|
422
|
+
* ```
|
|
384
423
|
*
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
*
|
|
388
|
-
*/
|
|
389
|
-
type Includes<TSource extends string | readonly string[], TValue extends string> = TSource extends string[] ? IsStringLiteral<TupleToUnion<TSource>> extends true ? IsLiteral<TValue> extends true ? TValue extends TupleToUnion<TSource> ? true : false : boolean : boolean : TSource extends string ? IsLiteral<TSource> extends true ? IsLiteral<TValue> extends true ? TSource extends `${string}${TValue}${string}` ? true : false : boolean : boolean : boolean;
|
|
390
|
-
|
|
391
|
-
type IsScalar<T extends Narrowable> = [T] extends [string] ? true : [T] extends [number] ? true : [T] extends [boolean] ? true : false;
|
|
392
|
-
/**
|
|
393
|
-
* **IfScalar**`<T, IF, ELSE>`
|
|
424
|
+
* All conditions (e.g., `startsWith`, `contains`, `notEqual`, etc.) that a particular filter
|
|
425
|
+
* is defined as having -- if there is more than one -- will be logically combined using AND
|
|
426
|
+
* unless specified otherwise in the third parameter.
|
|
394
427
|
*
|
|
395
|
-
*
|
|
428
|
+
* How a value of _undefined_ will be treated is stated in the second parameter but defaults
|
|
429
|
+
* to "no-impact" which means it's `false` when the logicCombinator is OR but defaults
|
|
430
|
+
* to `true` when the logicCombinator is AND.
|
|
396
431
|
*/
|
|
397
|
-
|
|
432
|
+
declare const filter: <F extends FilterDefn | NotFilter, U extends boolean | "no-impact", C extends LogicalCombinator>(config: F, logicCombinator?: C, ifUndefined?: U) => FilterFn<UnwrapNot<F>>;
|
|
398
433
|
|
|
399
434
|
/**
|
|
400
|
-
*
|
|
401
|
-
*
|
|
402
|
-
*
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* **IfUndefined**`<T, IF, ELSE>`
|
|
435
|
+
* Passing in an array of strings, you are passed back a dictionary with
|
|
436
|
+
* all the keys being the strings and values set to `true`.
|
|
437
|
+
* ```ts
|
|
438
|
+
* // { bar: true, bar: true } as const;
|
|
439
|
+
* const d - dictArr(arr);
|
|
407
440
|
*
|
|
408
|
-
*
|
|
409
|
-
*
|
|
441
|
+
* const fooBar = arrayToKeyLookup("foo", "bar");
|
|
442
|
+
* ```
|
|
410
443
|
*/
|
|
411
|
-
|
|
444
|
+
declare function arrayToKeyLookup<T extends readonly string[]>(...keys: T): Record<T[number], true>;
|
|
412
445
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
type IfExtends<T extends Narrowable, EXTENDS extends Narrowable, IF extends Narrowable, ELSE extends Narrowable> = Extends<T, EXTENDS> extends true ? IF : ELSE;
|
|
446
|
+
interface DefinePropertiesApi<T extends {}> {
|
|
447
|
+
/**
|
|
448
|
+
* Makes a property on the object **readonly** on the Javascript runtime
|
|
449
|
+
*/
|
|
450
|
+
ro<K extends keyof T>(prop: K, errorMsg?: (p: K, v: any) => string): Omit<T, K> & Record<K, Readonly<T[K]>>;
|
|
451
|
+
/**
|
|
452
|
+
* Makes a property on the object **read/writeable** on the Javascript runtime;
|
|
453
|
+
* this is the default so only use this where it is needed.
|
|
454
|
+
*/
|
|
455
|
+
rw<K extends keyof T>(prop: K): Omit<T, K> & Record<K, Readonly<T[K]>>;
|
|
456
|
+
}
|
|
457
|
+
declare function defineProperties<T extends {}>(obj: T): DefinePropertiesApi<T>;
|
|
426
458
|
|
|
427
459
|
/**
|
|
428
460
|
* Often when mutating the shape of an object you will end up with the union of a number of
|
|
@@ -433,2037 +465,1789 @@ type IfExtends<T extends Narrowable, EXTENDS extends Narrowable, IF extends Narr
|
|
|
433
465
|
type SimplifyObject<T extends {}> = ExpandRecursively<UnionToIntersection<ExpandRecursively<T>>>;
|
|
434
466
|
|
|
435
467
|
/**
|
|
436
|
-
*
|
|
437
|
-
*
|
|
438
|
-
*
|
|
439
|
-
* you have a value `T` which _might_ be **undefined** and a type `D` which
|
|
440
|
-
* defines all the _default_ type for `T`.
|
|
441
|
-
*
|
|
442
|
-
* - In all cases we compare first whether `T` is undefined and replace it's
|
|
443
|
-
* type with `D` 1-for-1 if it is
|
|
444
|
-
* - To address a larger set of use cases, when `D` _extends_ an object we will
|
|
445
|
-
* compare each property of `D` against `T`
|
|
468
|
+
* Given a dictionary of key/values, where the value is a function, this
|
|
469
|
+
* type utility will maintain the keys but change the values to whatever
|
|
470
|
+
* the `ReturnType` of the function was.
|
|
446
471
|
* ```ts
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
*
|
|
450
|
-
*
|
|
451
|
-
*
|
|
472
|
+
* const api = {
|
|
473
|
+
* val: 42,
|
|
474
|
+
* hi: (name: string) => `hi ${name}`,
|
|
475
|
+
* bye: (name: string) => `bye ${name}`
|
|
476
|
+
* };
|
|
477
|
+
* // { hi: string; bye: string }
|
|
478
|
+
* type Test = UnwrapValue<typeof api>
|
|
479
|
+
* // { val: number; foo: string; bar: string }
|
|
480
|
+
* type Test2 = UnwrapValue<typeof api, false>
|
|
452
481
|
* ```
|
|
453
482
|
*/
|
|
454
|
-
type
|
|
455
|
-
[K in keyof
|
|
456
|
-
}
|
|
457
|
-
D, // use D as the type
|
|
458
|
-
Exclude<T, undefined>> : IfUndefined<T, // check whether is T is undefined
|
|
459
|
-
D, // assign to D if it is
|
|
460
|
-
IfOptionalLiteral<T, // if T is a literal
|
|
461
|
-
IfExtends<D, T, D, // use D since it extends the value of T
|
|
462
|
-
Exclude<T, undefined>>, Exclude<T, undefined>>>;
|
|
463
|
-
|
|
464
|
-
/**
|
|
465
|
-
* **IsObject**
|
|
466
|
-
*
|
|
467
|
-
* Boolean type utility used to check whether a type `T` is an object
|
|
468
|
-
*/
|
|
469
|
-
type IsObject<T> = Mutable<T> extends Record<string, any> ? T extends FunctionType ? false : Mutable<T> extends any[] ? false : true : false;
|
|
470
|
-
/**
|
|
471
|
-
* **IfObject**
|
|
472
|
-
*
|
|
473
|
-
* Branch type utility with return `IF` when `T` extends an object type
|
|
474
|
-
* and `ELSE` otherwise
|
|
475
|
-
*/
|
|
476
|
-
type IfObject<T, IF extends Narrowable, ELSE extends Narrowable> = IsObject<T> extends true ? IF : ELSE;
|
|
483
|
+
type DictPartialApplication<T extends Record<string, any>, I extends boolean = true> = SimplifyObject<{
|
|
484
|
+
[K in keyof T]: T[K] extends (...args: any[]) => any ? Record<K, ReturnType<T[K]>> : true extends I ? never : Record<K, T[K]>;
|
|
485
|
+
}[keyof T]>;
|
|
477
486
|
|
|
478
487
|
/**
|
|
479
|
-
*
|
|
488
|
+
* Allow a dictionary have it's value's type changed to `T` while maintaining the keys in
|
|
489
|
+
* the original object `I` so long as the original value for the KV pair extends `V`.
|
|
480
490
|
*
|
|
481
|
-
*
|
|
491
|
+
* If `V` is not specified then it defaults to _any_ and therefore all KVs are preserved.
|
|
482
492
|
*
|
|
483
|
-
*
|
|
484
|
-
*
|
|
485
|
-
*
|
|
493
|
+
* ```ts
|
|
494
|
+
* type Obj = { foo: "hello", bar: 42, baz: () => "world" };
|
|
495
|
+
* // { foo: number, bar: number, baz: number };
|
|
496
|
+
* type AllNumbers = DictChangeValue<Obj, number>;
|
|
497
|
+
* // { foo: number }
|
|
498
|
+
* type StringToBool = DictChangeValue<Obj, boolean, string>
|
|
499
|
+
* ```
|
|
486
500
|
*/
|
|
487
|
-
type
|
|
501
|
+
type DictChangeValue<
|
|
502
|
+
/** the object who's value-type we're changing */
|
|
503
|
+
I extends Record<string, any>,
|
|
504
|
+
/** the return type that functions should be modified to have */
|
|
505
|
+
T extends any,
|
|
488
506
|
/**
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
* Type utility which converts type to `IF` type _if_ TValue _starts with_ `TStartsWith` but
|
|
492
|
-
* otherwise converts type to `ELSE`.
|
|
493
|
-
*
|
|
494
|
-
* Note, that there is also an optional `MAYBE` type
|
|
495
|
-
* which can be stated for cases where TValue or TStartsWith _might_ be the wider `string`
|
|
496
|
-
* type and therefore the type is unknown at design time.
|
|
507
|
+
*The type we expect in the value; if the value extends type `V` then the value will
|
|
508
|
+
* be converted to type `O`; if not then the KV pair will be discarded
|
|
497
509
|
*/
|
|
498
|
-
|
|
510
|
+
V extends any = any> = SimplifyObject<{
|
|
511
|
+
[K in keyof I]: I[K] extends V ? Record<K, T> : never;
|
|
512
|
+
}[keyof I]>;
|
|
499
513
|
|
|
500
514
|
/**
|
|
501
|
-
* **
|
|
502
|
-
*
|
|
503
|
-
* A type utility which checks whether `T` _ends with_ the string literal `U`.
|
|
515
|
+
* **DictPrependWithFn**
|
|
504
516
|
*
|
|
505
|
-
*
|
|
506
|
-
*
|
|
507
|
-
* just resolve to `boolean` as the value can not be known at design time..
|
|
508
|
-
*/
|
|
509
|
-
type EndsWith<TValue extends string, TEndsWith extends string> = IsStringLiteral<TEndsWith> extends true ? IsStringLiteral<TValue> extends true ? TValue extends `${string}${TEndsWith}` ? true : false : boolean : boolean;
|
|
510
|
-
/**
|
|
511
|
-
* **IfEndsWith**<TValue, TEndsWith, IF, ELSE, MAYBE>
|
|
517
|
+
* Given a strongly typed object `<T>`, this utility will inject a function call with
|
|
518
|
+
* arguments `<A>` and then return what had subsequently been the value of the property.
|
|
512
519
|
*
|
|
513
|
-
*
|
|
514
|
-
*
|
|
515
|
-
*
|
|
520
|
+
* Should you only want to apply this treatment to _some_ of the properties you can
|
|
521
|
+
* pass in a value `<E>` which will ensure that only properties which _extend_ `E` will be
|
|
522
|
+
* modified.
|
|
516
523
|
*/
|
|
517
|
-
type
|
|
524
|
+
type DictPrependWithFn<T extends Record<string, any>, A extends any[], E extends any = any> = SimplifyObject<{
|
|
525
|
+
[K in keyof T]: T[K] extends E ? Record<K, (...args: A) => T[K]> : Record<K, T[K]>;
|
|
526
|
+
}[keyof T]>;
|
|
518
527
|
|
|
519
528
|
/**
|
|
520
|
-
* **
|
|
529
|
+
* **DictReturnValues**
|
|
521
530
|
*
|
|
522
|
-
*
|
|
531
|
+
* A type utility which receives an object `<T>` and then modifies
|
|
532
|
+
* the return type of any properties which are a function to have this
|
|
533
|
+
* new **ReturnType** `<R>`. Optionally you can specify a particular return type which
|
|
534
|
+
* you are targeting and then
|
|
523
535
|
*/
|
|
524
|
-
type
|
|
536
|
+
type DictReturnValues<
|
|
537
|
+
/** the object which we expect to have props with function values */
|
|
538
|
+
T extends Record<string, any>,
|
|
539
|
+
/** the return type that functions should be modified to have */
|
|
540
|
+
R extends any,
|
|
541
|
+
/** optionally this utility can target only functions with a certain existing return value */
|
|
542
|
+
O extends (...args: any[]) => any = (...args: any[]) => any> = SimplifyObject<{
|
|
543
|
+
[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]>;
|
|
544
|
+
}[keyof T]>;
|
|
525
545
|
|
|
526
546
|
/**
|
|
527
|
-
*
|
|
547
|
+
* Expresses whether an option is "opt" (optional) or "req" (required)
|
|
528
548
|
*/
|
|
529
|
-
type
|
|
530
|
-
-readonly [K in keyof T]: IsObject<T[K]> extends true ? Mutable<T[K]> : T[K];
|
|
531
|
-
};
|
|
549
|
+
type OptRequired = "opt" | "req";
|
|
532
550
|
|
|
551
|
+
declare const DEFAULT_ONE_TO_MANY_MAPPING: FinalizedMapConfig<"req", "I -> O[]", "opt">;
|
|
552
|
+
declare const DEFAULT_ONE_TO_ONE_MAPPING: FinalizedMapConfig<"req", "I -> O", "req">;
|
|
553
|
+
declare const DEFAULT_MANY_TO_ONE_MAPPING: FinalizedMapConfig<"req", "I[] -> O", "req">;
|
|
554
|
+
type DefaultOneToManyMapping = typeof DEFAULT_ONE_TO_MANY_MAPPING;
|
|
555
|
+
type DefaultOneToOneMapping = typeof DEFAULT_ONE_TO_ONE_MAPPING;
|
|
556
|
+
type DefaultManyToOneMapping = typeof DEFAULT_MANY_TO_ONE_MAPPING;
|
|
533
557
|
/**
|
|
534
|
-
*
|
|
535
|
-
* ```ts
|
|
536
|
-
* const foo = 42;
|
|
537
|
-
* // 33
|
|
538
|
-
* type NotTheMeaningOfLife = Not<33, 42>;
|
|
539
|
-
* // never
|
|
540
|
-
* type NotTheMeaningOfLife = Not<42, 42>;
|
|
541
|
-
* ```
|
|
558
|
+
* **mapTo** _utility_
|
|
542
559
|
*
|
|
543
|
-
*
|
|
544
|
-
|
|
545
|
-
type Not<T, U> = T extends U ? never : T;
|
|
546
|
-
|
|
547
|
-
type Digital = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
|
|
548
|
-
type MakeArray<S extends string, T extends any[] = []> = S extends `${T["length"]}` ? T : MakeArray<S, [...T, 0]>;
|
|
549
|
-
type Multiply10<T extends any[]> = [...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T];
|
|
550
|
-
/**
|
|
551
|
-
* Converts a string literal to a numeric literal
|
|
560
|
+
* This utility -- by default -- creates a strongly typed 1:M data mapper which maps from one
|
|
561
|
+
* known source `I` to any array of another `O[]`:
|
|
552
562
|
* ```ts
|
|
553
|
-
*
|
|
554
|
-
*
|
|
555
|
-
*
|
|
556
|
-
* type Ten = Numeric<"10">;
|
|
563
|
+
* const mapper = mapTo<I, O>(i => [{
|
|
564
|
+
* foo: i.bar
|
|
565
|
+
* }]);
|
|
557
566
|
* ```
|
|
558
567
|
*/
|
|
559
|
-
|
|
560
|
-
|
|
568
|
+
declare const mapToFn: ConfiguredMap<DefaultOneToManyMapping>["map"];
|
|
561
569
|
/**
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
* Create an opaque type, which hides its internal details from the public, and
|
|
565
|
-
* can only be created by being used explicitly.
|
|
566
|
-
*
|
|
567
|
-
* Note: taken from [type-fest](https://github.com/sindresorhus/type-fest/blob/main/source/opaque.d.ts)
|
|
568
|
-
* repo.
|
|
570
|
+
* Provides a `config` method which allows the relationships between _inputs_
|
|
571
|
+
* and _outputs_ to be configured.
|
|
569
572
|
*/
|
|
570
|
-
|
|
571
|
-
readonly __opaque__: Token;
|
|
572
|
-
};
|
|
573
|
-
|
|
573
|
+
declare const mapToDict: MapperApi;
|
|
574
574
|
/**
|
|
575
|
-
* **
|
|
575
|
+
* **mapTo** _utility_
|
|
576
576
|
*
|
|
577
|
-
*
|
|
578
|
-
*
|
|
577
|
+
* This utility creates a strongly typed data mapper which maps from one
|
|
578
|
+
* known source `I` to another `O`.
|
|
579
579
|
*
|
|
580
|
+
* Signatures:
|
|
580
581
|
* ```ts
|
|
581
|
-
*
|
|
582
|
-
*
|
|
583
|
-
*
|
|
582
|
+
* const defMap = mapTo<I,O>( ... );
|
|
583
|
+
* const configured = mapTo.config({ output: "req" }).map<I,O>( ... );
|
|
584
|
+
* const one2one = mapTo.oneToOne().map<I,O>( ... );
|
|
585
|
+
* const many2one = mapTo.manyToOne().map<I,O>( ... );
|
|
584
586
|
* ```
|
|
585
|
-
*
|
|
586
|
-
* **Note:** in essence this is the _opposite_ of `Exclude<T,K>`
|
|
587
|
-
*/
|
|
588
|
-
type Retain<T, K extends keyof T> = Pick<T, Include<keyof T, K>>;
|
|
589
|
-
|
|
590
|
-
/**
|
|
591
|
-
* **SameKeys**
|
|
592
|
-
*
|
|
593
|
-
* Creates a _type_ with the same _keys_ as `T` but sets all values of these keys to `A` (which is
|
|
594
|
-
* **any** by default).
|
|
595
|
-
*
|
|
596
|
-
* Note: meant to be used as part of an _extends_ clause in most cases.
|
|
597
587
|
*/
|
|
598
|
-
|
|
599
|
-
[P in keyof T]: A;
|
|
600
|
-
};
|
|
588
|
+
declare const mapTo: (<I, O>(map: (source: I) => O[]) => Mapper<I, O, FinalizedMapConfig<"req", "I -> O[]", "opt">>) & MapperApi;
|
|
601
589
|
|
|
602
590
|
/**
|
|
603
|
-
* **
|
|
604
|
-
*
|
|
605
|
-
* A function responsible for transforming the _values_ of
|
|
606
|
-
* dictionary `I` into different _values_ for dictionary `O`.
|
|
591
|
+
* **Extends**`<T, EXTENDS>`
|
|
607
592
|
*
|
|
608
|
-
*
|
|
609
|
-
* are the same.
|
|
593
|
+
* Boolean type utility which returns `true` if `T` _extends_ `EXTENDS`.
|
|
610
594
|
*/
|
|
611
|
-
type
|
|
612
|
-
|
|
595
|
+
type Extends<T extends Narrowable, EXTENDS extends Narrowable> = T extends EXTENDS ? true : false;
|
|
613
596
|
/**
|
|
614
|
-
* **
|
|
597
|
+
* **IfExtends**
|
|
615
598
|
*
|
|
616
|
-
*
|
|
617
|
-
*
|
|
599
|
+
* Branching type utility which returns type `IF` when `E` _extends_ `T`; otherwise
|
|
600
|
+
* it will return the type `ELSE`.
|
|
618
601
|
*/
|
|
619
|
-
type
|
|
602
|
+
type IfExtends<T extends Narrowable, EXTENDS extends Narrowable, IF extends Narrowable, ELSE extends Narrowable> = Extends<T, EXTENDS> extends true ? IF : ELSE;
|
|
620
603
|
|
|
604
|
+
type IsBoolean<T> = [T] extends [boolean] ? true : false;
|
|
621
605
|
/**
|
|
622
|
-
*
|
|
623
|
-
*
|
|
624
|
-
* - `T` is either a dictionary (where keys will be used to compare) or
|
|
625
|
-
* a readonly sting array.
|
|
606
|
+
* Type utility which returns `true` or `false` based on
|
|
607
|
+
* whether the type holds the narrow "true" type.
|
|
626
608
|
* ```ts
|
|
627
|
-
*
|
|
628
|
-
*
|
|
629
|
-
*
|
|
609
|
+
* // true
|
|
610
|
+
* type T = IsTrue<true>;
|
|
611
|
+
* // boolean
|
|
612
|
+
* type U = IsTrue<boolean>;
|
|
613
|
+
* // false
|
|
614
|
+
* type F = IsTrue<false>;
|
|
615
|
+
* type F2 = IsTrue<"false">;
|
|
630
616
|
* ```
|
|
631
617
|
*/
|
|
632
|
-
type
|
|
633
|
-
|
|
634
|
-
}[keyof T];
|
|
618
|
+
type IsTrue<T extends Narrowable> = IsBoolean<T> extends true ? T extends true ? true : T extends false ? false : unknown : false;
|
|
619
|
+
type IsFalse<T extends Narrowable> = IsBoolean<T> extends true ? T extends false ? true : true extends T ? false : unknown : false;
|
|
635
620
|
/**
|
|
636
|
-
*
|
|
637
|
-
*
|
|
638
|
-
*
|
|
639
|
-
* a readonly sting array.
|
|
640
|
-
* ```ts
|
|
641
|
-
* const arr = ["foo", "bar", "baz"];
|
|
642
|
-
* // "foo"
|
|
643
|
-
* type F = WhereNot<typeof arr, `ba${string}`>;
|
|
644
|
-
* ```
|
|
645
|
-
*/
|
|
646
|
-
type WhereNot<T extends Record<string, any> | readonly string[], U> = T extends readonly string[] ? Exclude<T[number], U> : {
|
|
647
|
-
[K in keyof T]: K extends U ? never : K;
|
|
648
|
-
}[keyof T];
|
|
649
|
-
|
|
650
|
-
type AppendToObject<T, U extends keyof any, V> = {
|
|
651
|
-
[K in keyof T | U]: K extends keyof T ? T[K] : V;
|
|
652
|
-
};
|
|
653
|
-
/**
|
|
654
|
-
* Appends a new Key/Value to an existing dictionary <T>
|
|
655
|
-
*/
|
|
656
|
-
type AppendToDictionary<TDict, TKey extends string, TValue> = {
|
|
657
|
-
[K in keyof TDict | TKey]: K extends keyof TDict ? TDict[K] : TValue;
|
|
658
|
-
};
|
|
659
|
-
|
|
660
|
-
/**
|
|
661
|
-
* Accepts the `true` literal or _undefined_.
|
|
662
|
-
*/
|
|
663
|
-
type MaybeTrue = true | undefined;
|
|
664
|
-
/**
|
|
665
|
-
* Accepts the `false` literal or _undefined_.
|
|
621
|
+
* Type utility which checks for literal `true` value and then switches type
|
|
622
|
+
* to the IF, ELSE, or MAYBE generic types passed in where _maybe_ is when T
|
|
623
|
+
* is the wide type of `boolean`
|
|
666
624
|
*/
|
|
667
|
-
type
|
|
668
|
-
|
|
625
|
+
type IfTrue<T extends boolean, IF extends Narrowable, ELSE extends Narrowable, MAYBE extends Narrowable> = IsTrue<T> extends true ? IF : IsTrue<T> extends false ? ELSE : MAYBE;
|
|
669
626
|
/**
|
|
670
|
-
*
|
|
627
|
+
* Type utility which checks for literal `false` value and then switches type
|
|
628
|
+
* to the IF, ELSE, or MAYBE generic types passed in where _maybe_ is when T
|
|
629
|
+
* is the wide type of `boolean`
|
|
671
630
|
*/
|
|
672
|
-
type
|
|
631
|
+
type IfFalse<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable, MAYBE extends Narrowable> = IsFalse<T> extends true ? IF : IsTrue<T> extends false ? ELSE : MAYBE;
|
|
673
632
|
/**
|
|
674
|
-
*
|
|
633
|
+
* **IsBooleanLiteral**
|
|
634
|
+
*
|
|
635
|
+
* Type utility which returns true/false if the boolean value is a _boolean literal_ versus
|
|
636
|
+
* just the wider _boolean_ type.
|
|
675
637
|
*/
|
|
676
|
-
type
|
|
638
|
+
type IsBooleanLiteral<T extends Narrowable> = IsTrue<T> extends true ? true : IsFalse<T> extends true ? true : false;
|
|
677
639
|
/**
|
|
678
|
-
* **
|
|
679
|
-
*
|
|
680
|
-
* A partially applied type from the `ifTypeOf` utility where the base type has been
|
|
681
|
-
* defined and we now need to express the type which is intended to extend it.
|
|
640
|
+
* **IfBooleanLiteral**
|
|
682
641
|
*
|
|
683
|
-
*
|
|
684
|
-
* - `narrowlyExtends` - compares with _narrow_ / _literal_ types
|
|
642
|
+
* Branch utility which returns `IF` type when `T` is a boolean literal and `ELSE` otherwise
|
|
685
643
|
*/
|
|
686
|
-
type
|
|
687
|
-
extends: ExtendsClause<N, TValue>;
|
|
688
|
-
narrowlyExtends: ExtendsNarrowlyClause<N, TValue>;
|
|
689
|
-
};
|
|
644
|
+
type IfBooleanLiteral<T extends boolean, IF extends Narrowable, ELSE extends Narrowable> = IsBooleanLiteral<T> extends true ? IF : ELSE;
|
|
690
645
|
|
|
691
|
-
type LowerAlpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z";
|
|
692
|
-
/** Uppercase alphabetic character */
|
|
693
|
-
type UpperAlpha = Uppercase<LowerAlpha>;
|
|
694
646
|
/**
|
|
695
|
-
*
|
|
647
|
+
* **IsStringLiteral**
|
|
648
|
+
*
|
|
649
|
+
* Type utility which returns true/false if the string a _string literal_ versus
|
|
650
|
+
* just the _string_ type.
|
|
696
651
|
*/
|
|
697
|
-
type
|
|
698
|
-
type Whitespace = " " | "\n" | "\t";
|
|
699
|
-
type Punctuation = "." | "," | ";" | "!" | "?";
|
|
652
|
+
type IsStringLiteral<T extends Narrowable> = [T] extends [string] ? string extends T ? false : true : false;
|
|
700
653
|
/**
|
|
701
|
-
*
|
|
654
|
+
* **IfStringLiteral**
|
|
655
|
+
*
|
|
656
|
+
* Branch utility which returns `IF` type when `T` is a string literal and `ELSE` otherwise
|
|
702
657
|
*/
|
|
703
|
-
type
|
|
704
|
-
|
|
705
|
-
|
|
658
|
+
type IfStringLiteral<T extends string, IF extends Narrowable, ELSE extends Narrowable> = [
|
|
659
|
+
IsStringLiteral<T>
|
|
660
|
+
] extends [true] ? IF : ELSE;
|
|
706
661
|
/**
|
|
707
|
-
*
|
|
662
|
+
* **IsNumericLiteral**
|
|
663
|
+
*
|
|
664
|
+
* Type utility which returns true/false if the numeric value a _numeric literal_ versus
|
|
665
|
+
* just the _number_ type.
|
|
708
666
|
*/
|
|
709
|
-
type
|
|
667
|
+
type IsNumericLiteral<T extends number> = number extends T ? false : true;
|
|
710
668
|
/**
|
|
711
|
-
*
|
|
669
|
+
* **IfNumericLiteral**
|
|
670
|
+
*
|
|
671
|
+
* Branch utility which returns `IF` type when `T` is a numeric literal and `ELSE` otherwise
|
|
712
672
|
*/
|
|
713
|
-
type
|
|
673
|
+
type IfNumericLiteral<T extends number, IF extends Narrowable, ELSE extends Narrowable> = IsNumericLiteral<T> extends true ? IF : ELSE;
|
|
714
674
|
/**
|
|
715
|
-
*
|
|
675
|
+
* **IsLiteral**
|
|
676
|
+
*
|
|
677
|
+
* Type utility which returns true/false if the value passed -- a form of a
|
|
678
|
+
* string, number, or boolean -- is a _literal_ value of that type (true) or
|
|
679
|
+
* the more generic wide type (false).
|
|
716
680
|
*/
|
|
717
|
-
type
|
|
681
|
+
type IsLiteral<T> = [T] extends [string] ? IsStringLiteral<T> : [T] extends [boolean] ? IsBooleanLiteral<T> : [T] extends [number] ? IsNumericLiteral<T> : false;
|
|
718
682
|
/**
|
|
719
|
-
*
|
|
683
|
+
* **IsOptionalLiteral**
|
|
684
|
+
*
|
|
685
|
+
* Type utility which returns true/false if the value passed -- a form of a
|
|
686
|
+
* string, number, or boolean -- is a _literal_ value of that type (true) or
|
|
687
|
+
* the more generic wide type (false).
|
|
688
|
+
*
|
|
689
|
+
* This type also strips off _undefined_ from any possible union type to evaluate
|
|
690
|
+
* to `true` even when a literal value is in union with _undefined_. If you don't
|
|
691
|
+
* want to test for the union with _undefined_ use the `IsOptional` utility instead.
|
|
720
692
|
*/
|
|
721
|
-
type
|
|
693
|
+
type IsOptionalLiteral<T> = [Exclude<T, undefined>] extends [string] ? IsStringLiteral<Exclude<T, undefined>> : [Exclude<T, undefined>] extends [boolean] ? IsBooleanLiteral<Exclude<T, undefined>> : [Exclude<T, undefined>] extends [number] ? IsNumericLiteral<Exclude<T, undefined>> : false;
|
|
722
694
|
/**
|
|
723
|
-
*
|
|
724
|
-
*
|
|
695
|
+
* **IfLiteral**
|
|
696
|
+
*
|
|
697
|
+
* Branch type utility with return `IF` when `T` is a _literal_ value and `ELSE` otherwise
|
|
725
698
|
*/
|
|
726
|
-
type
|
|
727
|
-
type SpecialCharacters = "@" | "~" | "^" | "#" | "&" | "*";
|
|
699
|
+
type IfLiteral<T, IF extends Narrowable, ELSE extends Narrowable> = IsLiteral<T> extends true ? IF : ELSE;
|
|
728
700
|
/**
|
|
729
|
-
*
|
|
701
|
+
* **IfOptionalLiteral**
|
|
702
|
+
*
|
|
703
|
+
* Branch type utility with return `IF` when `T` is a _literal_ value (with possibly
|
|
704
|
+
* the inclusion of _undefined_); otherwise returns the type `ELSE`
|
|
730
705
|
*/
|
|
731
|
-
type
|
|
732
|
-
type Ipv4 = `${number}.${number}.${number}.${number}`;
|
|
706
|
+
type IfOptionalLiteral<T, IF extends Narrowable, ELSE extends Narrowable> = IsOptionalLiteral<T> extends true ? IF : ELSE;
|
|
733
707
|
|
|
734
708
|
/**
|
|
735
|
-
*
|
|
736
|
-
*
|
|
737
|
-
|
|
738
|
-
type RequiredKeys<T extends object, V extends any = any> = {
|
|
739
|
-
[K in keyof T]-?: {} extends {
|
|
740
|
-
[P in K]: T[K];
|
|
741
|
-
} ? never : T[K] extends V ? K : never;
|
|
742
|
-
}[keyof T];
|
|
743
|
-
/**
|
|
744
|
-
* Extracts the intersecting/common keys to two objects
|
|
709
|
+
* **IsUndefined**
|
|
710
|
+
*
|
|
711
|
+
* Boolean type utility returns `true` if `T` is undefined; `false` otherwise
|
|
745
712
|
*/
|
|
746
|
-
type
|
|
747
|
-
[K in keyof T]: K extends Keys<U> ? K : never;
|
|
748
|
-
}[keyof T];
|
|
713
|
+
type IsUndefined<T extends Narrowable> = T extends undefined ? true : false;
|
|
749
714
|
/**
|
|
750
|
-
*
|
|
751
|
-
*
|
|
715
|
+
* **IfUndefined**`<T, IF, ELSE>`
|
|
716
|
+
*
|
|
717
|
+
* Type utility which returns `IF` type when `T` is an _undefined_
|
|
718
|
+
* otherwise returns `ELSE` type.
|
|
752
719
|
*/
|
|
753
|
-
type
|
|
754
|
-
|
|
755
|
-
[P in K]: T[K];
|
|
756
|
-
} ? V extends T[K] ? K : never : never;
|
|
757
|
-
}[keyof T];
|
|
720
|
+
type IfUndefined<T, IF extends Narrowable, ELSE extends Narrowable> = IsUndefined<T> extends true ? IF : ELSE;
|
|
721
|
+
|
|
758
722
|
/**
|
|
759
|
-
*
|
|
723
|
+
* **TypeDefault**
|
|
760
724
|
*
|
|
761
|
-
*
|
|
762
|
-
*
|
|
725
|
+
* A type utility designed to help maintain strong and narrow types where
|
|
726
|
+
* you have a value `T` which _might_ be **undefined** and a type `D` which
|
|
727
|
+
* defines all the _default_ type for `T`.
|
|
728
|
+
*
|
|
729
|
+
* - In all cases we compare first whether `T` is undefined and replace it's
|
|
730
|
+
* type with `D` 1-for-1 if it is
|
|
731
|
+
* - To address a larger set of use cases, when `D` _extends_ an object we will
|
|
732
|
+
* compare each property of `D` against `T`
|
|
763
733
|
* ```ts
|
|
764
|
-
*
|
|
765
|
-
* type
|
|
734
|
+
* type I = { foo?: "foo" | undefined; bar?: 42 | 53 | undefined };
|
|
735
|
+
* type D = { foo: "foo"; bar: 53 };
|
|
736
|
+
* type DF = TypeDefault<I,D>; // `D`
|
|
737
|
+
* const i = { foo: undefined, bar: 99 } as const;
|
|
738
|
+
* type DF2 = TypeDefault<typeof i, D>; // `{ foo: "foo"; bar: 99 }`
|
|
766
739
|
* ```
|
|
767
740
|
*/
|
|
768
|
-
type
|
|
769
|
-
[K in keyof
|
|
770
|
-
}
|
|
741
|
+
type TypeDefault<T, D> = IsObject<D> extends true ? IsObject<T> extends true ? SimplifyObject<{
|
|
742
|
+
[K in keyof D]: K extends keyof T ? TypeDefault<T[K], D[K]> : D[K];
|
|
743
|
+
}> : IfUndefined<T, // check if T is undefined
|
|
744
|
+
D, // use D as the type
|
|
745
|
+
Exclude<T, undefined>> : IfUndefined<T, // check whether is T is undefined
|
|
746
|
+
D, // assign to D if it is
|
|
747
|
+
IfOptionalLiteral<T, // if T is a literal
|
|
748
|
+
IfExtends<D, T, D, // use D since it extends the value of T
|
|
749
|
+
Exclude<T, undefined>>, Exclude<T, undefined>>>;
|
|
750
|
+
|
|
771
751
|
/**
|
|
772
|
-
*
|
|
773
|
-
* an alphabetic character
|
|
752
|
+
* Expresses relationship between inputs/outputs:
|
|
774
753
|
*/
|
|
775
|
-
|
|
754
|
+
declare enum MapCardinality {
|
|
755
|
+
/** every input results in 0:M outputs */
|
|
756
|
+
OneToMany = "I -> O[]",
|
|
757
|
+
/** every input results in 0:1 outputs */
|
|
758
|
+
OneToOne = "I -> O",
|
|
759
|
+
/** every input is an array of type I and reduced to a single O */
|
|
760
|
+
ManyToOne = "I[] -> O"
|
|
761
|
+
}
|
|
762
|
+
type MapCardinalityIllustrated = EnumValues<MapCardinality>;
|
|
776
763
|
/**
|
|
777
|
-
*
|
|
778
|
-
*
|
|
779
|
-
*
|
|
764
|
+
* The _user_ configuration of a **mapTo** mapper function
|
|
765
|
+
* which will be finalized by merging it with the appropriate
|
|
766
|
+
* default mapping type.
|
|
780
767
|
*/
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
768
|
+
interface MapConfig<IR extends OptRequired | undefined = undefined, D extends MapCardinalityIllustrated | undefined = undefined, OR extends OptRequired | undefined = undefined> {
|
|
769
|
+
input?: IR;
|
|
770
|
+
output?: OR;
|
|
771
|
+
cardinality?: D;
|
|
772
|
+
/**
|
|
773
|
+
* Whether calls to the final `MapFn` will be logged to stderr
|
|
774
|
+
* for debugging purposes. Defaults to false; if you specify
|
|
775
|
+
* a _string_ for a value that will be sent to stderr along
|
|
776
|
+
* with other debugging info.
|
|
777
|
+
*/
|
|
778
|
+
debug?: boolean | string;
|
|
779
|
+
}
|
|
784
780
|
/**
|
|
785
|
-
* **
|
|
781
|
+
* A finalized configuration of a **mapTo** mapper functions cardinality
|
|
782
|
+
* relationships between _inputs_ and _outputs_.
|
|
786
783
|
*
|
|
787
|
-
*
|
|
788
|
-
*
|
|
784
|
+
* Note: _this configuration does _not_ yet include the actual mapping
|
|
785
|
+
* configuration between the input and output._
|
|
789
786
|
*/
|
|
790
|
-
type
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
[K in keyof T]: K extends string ? Readonly<K> : never;
|
|
795
|
-
}[keyof T];
|
|
787
|
+
type FinalizedMapConfig<IR extends OptRequired = MapIR<DefaultOneToManyMapping>, D extends MapCardinalityIllustrated = MapCard<DefaultOneToManyMapping>, OR extends OptRequired = MapOR<DefaultOneToManyMapping>> = Required<Omit<MapConfig<IR, D, OR>, "debug">> & {
|
|
788
|
+
finalized: true;
|
|
789
|
+
debug: boolean | string;
|
|
790
|
+
};
|
|
796
791
|
/**
|
|
797
|
-
*
|
|
792
|
+
* User configuration exposed by a config function which specifies the
|
|
793
|
+
* cardinality already (e.g., `oneToMany()`, `manyToOne()`)
|
|
798
794
|
*/
|
|
799
|
-
type
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
* Reduces an object type to only key/value pairs where the key is required
|
|
812
|
-
*/
|
|
813
|
-
type RequiredProps<T extends object> = Pick<T, RequiredKeys<T>>;
|
|
814
|
-
/**
|
|
815
|
-
* **OptionalProps**
|
|
816
|
-
*
|
|
817
|
-
* Reduces an object to only key/value pairs where the key is optional
|
|
818
|
-
*/
|
|
819
|
-
type OptionalProps<T extends object> = Pick<T, OptionalKeys<T>>;
|
|
795
|
+
type MapCardinalityConfig<IR extends OptRequired | undefined, OR extends OptRequired | undefined> = {
|
|
796
|
+
/** whether we the input can _optionally_ be an `undefined` value or not */
|
|
797
|
+
input?: IR;
|
|
798
|
+
/** whether we the output can _optionally_ be an `undefined` value or not */
|
|
799
|
+
output?: OR;
|
|
800
|
+
/**
|
|
801
|
+
* Whether calls to the final `MapFn` will be logged to stderr
|
|
802
|
+
* for debugging purposes. Defaults to false; if you set to a string
|
|
803
|
+
* value than this will be echoed out with stderr.
|
|
804
|
+
*/
|
|
805
|
+
debug?: boolean | string;
|
|
806
|
+
};
|
|
820
807
|
/**
|
|
821
|
-
* **
|
|
808
|
+
* **ConfiguredMap**
|
|
822
809
|
*
|
|
823
|
-
*
|
|
824
|
-
*
|
|
825
|
-
*
|
|
826
|
-
* const foo = { a: 1, b: "hi", c: () => "hello" }
|
|
827
|
-
* // { c: () => "hello" }
|
|
828
|
-
* type W = WithValue<Function, typeof foo>
|
|
829
|
-
* ```
|
|
810
|
+
* A partial application of the mapTo() utility which has expressed the
|
|
811
|
+
* configuration of the _inputs_ and _outputs_ and provides a `.map()`
|
|
812
|
+
* method which allows the user configure the specifics of the mapping.
|
|
830
813
|
*/
|
|
831
|
-
type
|
|
814
|
+
type ConfiguredMap<C extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = {
|
|
815
|
+
map: <I, O>(map: MapTo<I, O, C>) => Mapper<I, O, C>;
|
|
816
|
+
input: MapIR<C>;
|
|
817
|
+
cardinality: MapCard<C>;
|
|
818
|
+
output: MapOR<C>;
|
|
819
|
+
debug: boolean | string;
|
|
820
|
+
};
|
|
832
821
|
/**
|
|
833
|
-
*
|
|
834
|
-
* string.
|
|
822
|
+
* Extracts the IR, Cardinality, and OR generics from a FinalizedMapConfig
|
|
835
823
|
*/
|
|
836
|
-
type
|
|
824
|
+
type DecomposeMapConfig<M extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = M extends MapConfig<infer IR, infer D, infer OR> ? IR extends OptRequired | undefined ? D extends MapCardinalityIllustrated | undefined ? OR extends OptRequired | undefined ? [IR, D, OR] : never : never : never : M extends FinalizedMapConfig<infer IR, infer D, infer OR> ? IR extends OptRequired ? D extends MapCardinalityIllustrated ? OR extends OptRequired ? [IR, D, OR] : never : never : never : never;
|
|
825
|
+
/** extracts IR from a `FinalizedMapConfig` */
|
|
826
|
+
type MapIR<T extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = DecomposeMapConfig<T>[0];
|
|
837
827
|
/**
|
|
838
|
-
*
|
|
828
|
+
* extracts the MapCardinality from a `FinalizedMapConfig`
|
|
839
829
|
*/
|
|
840
|
-
type
|
|
841
|
-
|
|
830
|
+
type MapCard<T extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = DecomposeMapConfig<T>[1];
|
|
831
|
+
/** extracts OR from a `FinalizedMapConfig` */
|
|
832
|
+
type MapOR<T extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = DecomposeMapConfig<T>[2];
|
|
842
833
|
/**
|
|
843
|
-
*
|
|
844
|
-
*
|
|
845
|
-
* A rule definition is the typing for the fluent API surface that is built up
|
|
846
|
-
* with the **ruleset** utility.
|
|
834
|
+
* Merges the types of a userland configuration with a default configuration
|
|
847
835
|
*/
|
|
848
|
-
type
|
|
849
|
-
|
|
850
|
-
T extends object,
|
|
851
|
-
/** the optional props -- as a union type -- which must be defined per the rule */
|
|
852
|
-
H extends string = "",
|
|
853
|
-
/** the key/values which will be evaluated on execution (wide type) */
|
|
854
|
-
E extends Partial<SameKeys<T>> = {},
|
|
855
|
-
/** the key/values which will be evaluated on execution (narrow type) */
|
|
856
|
-
N extends Partial<SameKeys<T>> = {}> = {
|
|
836
|
+
type AsFinalizedConfig<U extends MapConfig<OptRequired | undefined, MapCardinalityIllustrated | undefined, OptRequired | undefined>, D extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = TypeDefault<U, D> extends FinalizedMapConfig<infer IR, infer C, infer OR> ? FinalizedMapConfig<IR, C, OR> : never;
|
|
837
|
+
type MapperApi = {
|
|
857
838
|
/**
|
|
858
|
-
*
|
|
859
|
-
*
|
|
839
|
+
* Provides opportunity to configure _input_, _output_, and _cardinality_
|
|
840
|
+
* prior to providing a mapping function.
|
|
841
|
+
*
|
|
842
|
+
* Note: _the defaults for configuration are defined by the_ `DEFAULT_ONE_TO_MANY_MAPPING`
|
|
843
|
+
* _constant made available as a symbol from this library._
|
|
860
844
|
*/
|
|
861
|
-
|
|
845
|
+
config: <C extends MapConfig<OptRequired, //
|
|
846
|
+
MapCardinalityIllustrated, OptRequired>>(config: C) => ConfiguredMap<AsFinalizedConfig<C, //
|
|
847
|
+
DefaultOneToManyMapping>>;
|
|
862
848
|
/**
|
|
863
|
-
*
|
|
864
|
-
*
|
|
849
|
+
* Provides a nice 1:1 ratio between the input and output.
|
|
850
|
+
*
|
|
851
|
+
* By default the input and output are considered to be _required_
|
|
852
|
+
* properties but this can be changed with the options hash provided.
|
|
853
|
+
* ```ts
|
|
854
|
+
* const mapper = mapTo.oneToOne().map(...);
|
|
855
|
+
* // add in ability to filter out some inputs
|
|
856
|
+
* const mapAndFilter = mapTo.oneToOne({ output: "opt" })
|
|
857
|
+
* ```
|
|
865
858
|
*/
|
|
866
|
-
|
|
859
|
+
oneToOne: <C extends MapCardinalityConfig<OptRequired, OptRequired>>(config?: C) => ConfiguredMap<AsFinalizedConfig<C, //
|
|
860
|
+
DefaultOneToOneMapping>>;
|
|
867
861
|
/**
|
|
868
|
-
*
|
|
869
|
-
*
|
|
870
|
-
*
|
|
862
|
+
* **manyToOne** _mapping_
|
|
863
|
+
*
|
|
864
|
+
* Provides a configuration where multiple inputs `I[]` will be mapped to a
|
|
865
|
+
* single output `O`.
|
|
866
|
+
*
|
|
867
|
+
* Choosing this configuration will, by default, set both input and output
|
|
868
|
+
* to be "required" but you can change this default if you so choose.
|
|
871
869
|
*/
|
|
872
|
-
|
|
870
|
+
manyToOne: <C extends MapCardinalityConfig<OptRequired | undefined, //
|
|
871
|
+
//
|
|
872
|
+
OptRequired | undefined>>(config?: C) => ConfiguredMap<AsFinalizedConfig<C, //
|
|
873
|
+
DefaultManyToOneMapping>>;
|
|
874
|
+
oneToMany: <C extends MapCardinalityConfig<OptRequired | undefined, //
|
|
875
|
+
//
|
|
876
|
+
OptRequired | undefined>>(config?: C) => ConfiguredMap<AsFinalizedConfig<C, //
|
|
877
|
+
DefaultOneToManyMapping>>;
|
|
873
878
|
};
|
|
879
|
+
type MapInput<I, //
|
|
880
|
+
IR extends OptRequired, C extends MapCardinalityIllustrated> = C extends MapCardinality.OneToMany | "I -> O[]" ? IR extends "opt" ? I | undefined : I : C extends MapCardinality.OneToOne | "I -> O" ? IR extends "opt" ? I | undefined : I : C extends MapCardinality.ManyToOne | "I[] -> O" ? IR extends "opt" ? I[] | undefined : I[] : never;
|
|
881
|
+
type MapOutput<O, //
|
|
882
|
+
OR extends OptRequired, C extends MapCardinalityIllustrated> = C extends MapCardinality.OneToMany | "I -> O[]" ? OR extends "opt" ? O[] : [O, ...O[]] : C extends MapCardinality.OneToOne | "I -> O" ? OR extends "opt" ? O | null : O : C extends MapCardinality.ManyToOne | "I[] -> O" ? OR extends "opt" ? O | null : O : never;
|
|
874
883
|
/**
|
|
875
|
-
* **
|
|
884
|
+
* **MapTo<I, O>**
|
|
876
885
|
*
|
|
877
|
-
* A
|
|
878
|
-
*
|
|
879
|
-
* or `false`.
|
|
886
|
+
* A mapping function between an input type `I` and output type `O`. Defaults to using
|
|
887
|
+
* the _default_ OneToMany mapping config.
|
|
880
888
|
*
|
|
881
|
-
*
|
|
882
|
-
*
|
|
883
|
-
* // type-safe way to check whether optional prop is actually set
|
|
884
|
-
* const rule: DynamicRule<State> = s => s
|
|
885
|
-
* .has("id")
|
|
886
|
-
* .equals("favorite", true)
|
|
887
|
-
* .equals("color", "red");
|
|
888
|
-
* ```
|
|
889
|
+
* **Note:** this type is designed to guide the userland mapping; refer
|
|
890
|
+
* to `MapFn` if you want the type output by the `mapFn()` utility.
|
|
889
891
|
*/
|
|
890
|
-
type
|
|
892
|
+
type MapTo<I, O, C extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired> = DefaultOneToManyMapping> = MapIR<C> extends "opt" ? (source?: MapInput<I, MapIR<C>, MapCard<C>>) => MapOutput<O, MapOR<C>, MapCard<C>> : (source: MapInput<I, MapIR<C>, MapCard<C>>) => MapOutput<O, MapOR<C>, MapCard<C>>;
|
|
893
|
+
type MapFnOutput<I, O, S, OR extends OptRequired, C extends MapCardinalityIllustrated> = C extends "I -> O[]" | MapCardinality.OneToMany ? S extends I[] ? OR extends "opt" ? O[] : [O, ...O[]] : OR extends "opt" ? O[] | null : O[] : C extends MapCardinality.OneToOne | "I -> O" ? S extends I[] ? OR extends "opt" ? O[] : [O, ...O[]] : OR extends "opt" ? O | null : O : C extends MapCardinality.ManyToOne | "I[] -> O" ? S extends I[][] ? OR extends "opt" ? O[] : [O, ...O[]] : OR extends "opt" ? O | null : O : never;
|
|
894
|
+
type MapFnInput<I, IR extends OptRequired, D extends MapCardinalityIllustrated> = D extends "I -> O[]" | MapCardinality.OneToMany ? IR extends "opt" ? I | I[] | undefined : I | I[] : D extends MapCardinality.OneToOne | "I -> O" ? IR extends "opt" ? I | I[] | undefined : I | I[] : D extends MapCardinality.ManyToOne | "I[] -> O" ? IR extends "opt" ? I[] | I[][] | undefined : I[] | I[][] : never;
|
|
891
895
|
/**
|
|
892
|
-
*
|
|
896
|
+
* The mapping function provided by the `mapFn()` utility. This _fn_
|
|
897
|
+
* is intended to be used in two ways:
|
|
893
898
|
*
|
|
894
|
-
*
|
|
895
|
-
*
|
|
899
|
+
* 1. Iterative:
|
|
900
|
+
* ```ts
|
|
901
|
+
* const m = mapTo<I,O>(i => [ ... ]);
|
|
902
|
+
* // maps inputs to outputs
|
|
903
|
+
* const out = inputs.map(m);
|
|
904
|
+
* ```
|
|
905
|
+
* 2. Block:
|
|
906
|
+
* ```ts
|
|
907
|
+
* // maps inputs to outputs (filtering or splitting where appr.)
|
|
908
|
+
* const out2 = m(inputs);
|
|
909
|
+
* ```
|
|
896
910
|
*/
|
|
897
|
-
type
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
911
|
+
type MapFn<I, O, C extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = MapIR<C> extends "opt" ? <S extends MapFnInput<I, MapIR<C>, MapCard<C>>>(source?: S) => MapFnOutput<I, O, S, MapOR<C>, MapCard<C>> : <S extends MapFnInput<I, MapIR<C>, MapCard<C>>>(source: S) => MapFnOutput<I, O, S, MapOR<C>, MapCard<C>>;
|
|
912
|
+
/**
|
|
913
|
+
* **Mapper**
|
|
914
|
+
*
|
|
915
|
+
* A fully configured _mapper_ stemming from the **mapTo()** utility. It is both a mapping
|
|
916
|
+
* function and a dictionary which describes the mapper's properties.
|
|
917
|
+
* ```ts
|
|
918
|
+
* const m = mapTo.oneToOne().map( ... );
|
|
919
|
+
* const mapped = m(inputs);
|
|
920
|
+
* const mappedOver = inputs.map(m);
|
|
921
|
+
* ```
|
|
922
|
+
*
|
|
923
|
+
* Note: the root of a `Mapper` is the mapper function but
|
|
924
|
+
* this is combined with a dictionary of settings and types
|
|
925
|
+
* which you can use. For instance, look at the `fnSignature`
|
|
926
|
+
* property to get the _type_ signature of the map function.
|
|
927
|
+
*/
|
|
928
|
+
type Mapper<I = unknown, O = unknown, C extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired> = FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = {
|
|
929
|
+
input: MapIR<C>;
|
|
930
|
+
output: MapOR<C>;
|
|
931
|
+
cardinality: MapCard<C>;
|
|
932
|
+
debug: boolean | string;
|
|
933
|
+
inputType: I;
|
|
934
|
+
outputType: O;
|
|
908
935
|
/**
|
|
909
|
-
* Provides the _type_
|
|
910
|
-
*
|
|
911
|
-
* ```ts
|
|
912
|
-
* const t = number();
|
|
913
|
-
* // number
|
|
914
|
-
* type T = typeof t.type;
|
|
915
|
-
* ```
|
|
936
|
+
* Provides the _type_ information for mapper function.
|
|
916
937
|
*
|
|
917
|
-
*
|
|
918
|
-
*
|
|
919
|
-
* const t = number();
|
|
920
|
-
* // "number"
|
|
921
|
-
* console.log(t.type);
|
|
922
|
-
* ```
|
|
938
|
+
* Note: _this is just a **type**_ not the actual function which positioned
|
|
939
|
+
* at the root of the Mapper type
|
|
923
940
|
*/
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
};
|
|
927
|
-
type TypeOptions<T extends Partial<object> = {}> = {
|
|
928
|
-
/** each type has a default type guard but you can override if you need to be more specific */
|
|
929
|
-
typeGuard?: TypeGuard<T>;
|
|
930
|
-
} & T;
|
|
931
|
-
|
|
941
|
+
fnSignature: MapFn<I, O, C>;
|
|
942
|
+
} & MapFn<I, O, C>;
|
|
932
943
|
/**
|
|
933
|
-
*
|
|
944
|
+
* **MapInputFrom**
|
|
945
|
+
*
|
|
946
|
+
* Type utility which extracts the `I` type from a fully configured `Mapper`
|
|
934
947
|
*/
|
|
935
|
-
type
|
|
948
|
+
type MapInputFrom<T extends Mapper> = T extends Mapper<infer I> ? I : never;
|
|
936
949
|
/**
|
|
937
|
-
*
|
|
950
|
+
* **MapOutputFrom**
|
|
951
|
+
*
|
|
952
|
+
* Type utility which extracts the output [`O`] type from a fully configured `Mapper`
|
|
938
953
|
*/
|
|
939
|
-
type
|
|
954
|
+
type MapOutputFrom<T extends Mapper> = T extends Mapper<any, infer O> ? O : never;
|
|
940
955
|
/**
|
|
941
|
-
*
|
|
956
|
+
* **MapCardinalityFrom**
|
|
957
|
+
*
|
|
958
|
+
* Type utility which extracts _cardinality_ of a `Mapper`'s inputs to outputs
|
|
942
959
|
*/
|
|
943
|
-
type
|
|
960
|
+
type MapCardinalityFrom<T extends Mapper> = T extends Mapper<any, any, infer C> ? C extends FinalizedMapConfig<OptRequired, infer Cardinality, OptRequired> ? Cardinality : never : never;
|
|
944
961
|
|
|
945
962
|
/**
|
|
946
|
-
*
|
|
963
|
+
* Given a dictionary of type `<T>`, this utility function will
|
|
964
|
+
* make the `<M>` generic property _mutable_ and all other _read-only_.
|
|
965
|
+
*
|
|
947
966
|
* ```ts
|
|
948
|
-
* //
|
|
949
|
-
* type
|
|
950
|
-
*
|
|
951
|
-
*
|
|
952
|
-
*
|
|
953
|
-
* type T = AllCaps<string>;
|
|
967
|
+
* // { foo: string, bar?: Readonly<number> }
|
|
968
|
+
* type Example = MutableProps<{
|
|
969
|
+
* foo: Readonly<string>,
|
|
970
|
+
* bar?: number
|
|
971
|
+
* }, "foo">;
|
|
954
972
|
* ```
|
|
955
973
|
*/
|
|
956
|
-
type
|
|
974
|
+
type MutableProps<T extends {}, M extends keyof T & string> = ExpandRecursively<Mutable<Pick<T, M>> & Readonly<Pick<T, Keys<T, M>>>>;
|
|
957
975
|
|
|
958
976
|
/**
|
|
959
|
-
*
|
|
960
|
-
*
|
|
961
|
-
*
|
|
962
|
-
*
|
|
963
|
-
* // ["the", " long and winding road"]
|
|
964
|
-
* type T1 = Break<"the long and winding road", " ">;
|
|
965
|
-
* // ["there", " I was, there I was"]
|
|
966
|
-
* type T2 = Break<"there I was, there I was", " ">;
|
|
967
|
-
* ```
|
|
968
|
-
*/
|
|
969
|
-
type Break<T extends string, D extends string> = (string extends T ? [string, string] : (T extends `${infer F}${D}${infer _R}` ? (F extends `${infer _X}${D}${infer _Y}` ? never : (T extends `${F}${infer R}` ? [F, R] : never)) : [T, ""]));
|
|
970
|
-
|
|
971
|
-
/**
|
|
972
|
-
* Concatenates two arrays (of literals).
|
|
977
|
+
* Given a dictionary of type `<T>`, this utility function will
|
|
978
|
+
* make the `<R>` generic property _required_ (use a union to make
|
|
979
|
+
* more than one prop required).
|
|
980
|
+
*
|
|
973
981
|
* ```ts
|
|
974
|
-
* //
|
|
975
|
-
* type
|
|
982
|
+
* // { foo: string, bar?: number }
|
|
983
|
+
* type Example = RequireProps<{foo?: string, bar?: number}, "foo">;
|
|
976
984
|
* ```
|
|
977
985
|
*/
|
|
978
|
-
type
|
|
986
|
+
type RequireProps<T extends {}, R extends keyof T> = ExpandRecursively<Required<Pick<T, R>> & T>;
|
|
979
987
|
|
|
980
988
|
/**
|
|
981
|
-
*
|
|
982
|
-
* ```ts
|
|
983
|
-
* const fooy = "fooy";
|
|
984
|
-
* // "Foo"
|
|
985
|
-
* type Foo = Replace<typeof fooy, "y", "">;
|
|
986
|
-
* ```
|
|
989
|
+
* **SameKeys**
|
|
987
990
|
*
|
|
988
|
-
*
|
|
991
|
+
* Creates a _type_ with the same _keys_ as `T` but sets all values of these keys to `A` (which is
|
|
992
|
+
* **any** by default).
|
|
993
|
+
*
|
|
994
|
+
* Note: meant to be used as part of an _extends_ clause in most cases.
|
|
989
995
|
*/
|
|
990
|
-
type
|
|
996
|
+
type SameKeys<T extends object, A extends any = any> = {
|
|
997
|
+
[P in keyof T]: A;
|
|
998
|
+
};
|
|
991
999
|
|
|
1000
|
+
type LowerAlpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z";
|
|
1001
|
+
/** Uppercase alphabetic character */
|
|
1002
|
+
type UpperAlpha = Uppercase<LowerAlpha>;
|
|
992
1003
|
/**
|
|
993
|
-
*
|
|
994
|
-
* ```ts
|
|
995
|
-
* // "foobar "
|
|
996
|
-
* type T = TrimLeft<"\n\t foobar ">;
|
|
997
|
-
* // string
|
|
998
|
-
* type T = TrimLeft<string>;
|
|
999
|
-
* ```
|
|
1004
|
+
* Alphabetical characters (upper and lower)
|
|
1000
1005
|
*/
|
|
1001
|
-
type
|
|
1002
|
-
|
|
1006
|
+
type Alpha = UpperAlpha | LowerAlpha;
|
|
1007
|
+
type Whitespace = " " | "\n" | "\t";
|
|
1008
|
+
type Punctuation = "." | "," | ";" | "!" | "?";
|
|
1003
1009
|
/**
|
|
1004
|
-
*
|
|
1005
|
-
* ```ts
|
|
1006
|
-
* // "\n\t "
|
|
1007
|
-
* type T = LeftWhitespace<"\n\t foobar">;
|
|
1008
|
-
* ```
|
|
1010
|
+
* Characters which typically are used to separate words (but not including a space)
|
|
1009
1011
|
*/
|
|
1010
|
-
type
|
|
1011
|
-
|
|
1012
|
+
type StringDelimiter = "_" | "-" | "/" | "\\";
|
|
1013
|
+
type OpeningBracket = "(" | "[" | "{";
|
|
1014
|
+
type ClosingBracket = ")" | "]" | "}";
|
|
1012
1015
|
/**
|
|
1013
|
-
*
|
|
1014
|
-
* ```ts
|
|
1015
|
-
* // "\n foobar"
|
|
1016
|
-
* type T = TrimRight<"\n foobar \t">;
|
|
1017
|
-
* // string
|
|
1018
|
-
* type T = TrimRight<string>;
|
|
1019
|
-
* ```
|
|
1016
|
+
* Opening and closing parenthesis
|
|
1020
1017
|
*/
|
|
1021
|
-
type
|
|
1022
|
-
|
|
1018
|
+
type Parenthesis = "(" | ")";
|
|
1023
1019
|
/**
|
|
1024
|
-
*
|
|
1025
|
-
* ```ts
|
|
1026
|
-
* // "\n\t "
|
|
1027
|
-
* type T = LeftWhitespace<"\n\t foobar">;
|
|
1028
|
-
* ```
|
|
1020
|
+
* Opening and closing brackets
|
|
1029
1021
|
*/
|
|
1030
|
-
type
|
|
1031
|
-
|
|
1022
|
+
type Bracket = OpeningBracket | ClosingBracket;
|
|
1032
1023
|
/**
|
|
1033
|
-
*
|
|
1034
|
-
* is _not_ limited to TS's recursive string length of roughly 48.
|
|
1035
|
-
*
|
|
1036
|
-
* ```ts
|
|
1037
|
-
* // 3
|
|
1038
|
-
* type Three = StringLength<"foo">;
|
|
1039
|
-
* ```
|
|
1024
|
+
* Numeric string characters
|
|
1040
1025
|
*/
|
|
1041
|
-
type
|
|
1042
|
-
|
|
1026
|
+
type NumericString = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
|
|
1043
1027
|
/**
|
|
1044
|
-
*
|
|
1045
|
-
* ```ts
|
|
1046
|
-
* // "foobar"
|
|
1047
|
-
* type T = Trim<"\n\t foobar ">;
|
|
1048
|
-
* // string
|
|
1049
|
-
* type T = Trim<string>;
|
|
1050
|
-
* ```
|
|
1028
|
+
* Any alphabetic or numeric string character
|
|
1051
1029
|
*/
|
|
1052
|
-
type
|
|
1053
|
-
|
|
1030
|
+
type AlphaNumeric = Alpha | NumericString;
|
|
1054
1031
|
/**
|
|
1055
|
-
*
|
|
1032
|
+
* Allows alphanumeric characters and some special characters typically allowed
|
|
1033
|
+
* in variable names.
|
|
1056
1034
|
*/
|
|
1057
|
-
type
|
|
1058
|
-
type
|
|
1059
|
-
type Zip4 = `${NumericString}${string}`;
|
|
1035
|
+
type VariableName = AlphaNumeric | "_" | "." | "-";
|
|
1036
|
+
type SpecialCharacters = "@" | "~" | "^" | "#" | "&" | "*";
|
|
1060
1037
|
/**
|
|
1061
|
-
*
|
|
1038
|
+
* Non-alphabetic characters including whitespace, string numerals, and
|
|
1062
1039
|
*/
|
|
1063
|
-
type
|
|
1064
|
-
|
|
1065
|
-
/**
|
|
1066
|
-
* If **ALL CAPS** it converts to all lowercase; if not then it does nothing */
|
|
1067
|
-
type LowerAllCaps<T extends string> = AllCaps<T> extends true ? Lowercase<T> : T;
|
|
1040
|
+
type NonAlpha = Whitespace | Punctuation | NumericString | Bracket | SpecialCharacters;
|
|
1041
|
+
type Ipv4 = `${number}.${number}.${number}.${number}`;
|
|
1068
1042
|
|
|
1069
|
-
type Delimiter = "_" | "-" | " ";
|
|
1070
|
-
/** convert all delimiters to dashes */
|
|
1071
|
-
type DashDelim<T extends string> = T extends `${infer Begin}${" "}${infer Rest}` ? DashDelim<`${Begin}-${Rest}`> : T extends `${infer Begin}${"_"}${infer Rest}` ? DashDelim<`${Begin}-${Rest}`> : T;
|
|
1072
1043
|
/**
|
|
1073
|
-
*
|
|
1074
|
-
*
|
|
1075
|
-
* // "FooBar"
|
|
1076
|
-
* type T = PascalCase<"fooBar">;
|
|
1077
|
-
* type T = PascalCase<"foo-bar">;
|
|
1078
|
-
* type T = PascalCase<"foo_bar">;
|
|
1079
|
-
* type T = PascalCase<"\n foo_bar \t">;
|
|
1080
|
-
* ```
|
|
1044
|
+
* Extracts the _required_ keys in the object's type. You also may
|
|
1045
|
+
* optionally filter by the _value_ of the key.
|
|
1081
1046
|
*/
|
|
1082
|
-
type
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1047
|
+
type RequiredKeys<T extends object, V extends any = any> = {
|
|
1048
|
+
[K in keyof T]-?: {} extends {
|
|
1049
|
+
[P in K]: T[K];
|
|
1050
|
+
} ? never : T[K] extends V ? K : never;
|
|
1051
|
+
}[keyof T];
|
|
1086
1052
|
/**
|
|
1087
|
-
*
|
|
1053
|
+
* Extracts the intersecting/common keys to two objects
|
|
1088
1054
|
*/
|
|
1089
|
-
type
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1055
|
+
type IntersectingKeys<T extends Record<string, any> | readonly string[], U extends Record<string, any> | readonly string[]> = {
|
|
1056
|
+
[K in keyof T]: K extends Keys<U> ? K : never;
|
|
1057
|
+
}[keyof T];
|
|
1093
1058
|
/**
|
|
1094
|
-
*
|
|
1095
|
-
*
|
|
1096
|
-
* // true
|
|
1097
|
-
* type T = HasUppercase<"Foobar">;
|
|
1098
|
-
* // false
|
|
1099
|
-
* type T = HasUppercase<"foobar">;
|
|
1100
|
-
* // "unknown"
|
|
1101
|
-
* type T = HasUppercase<string>;
|
|
1102
|
-
* ```
|
|
1059
|
+
* Extracts the _optional_ keys in the object's type. You also may
|
|
1060
|
+
* optionally filter by the _value_ of the key.
|
|
1103
1061
|
*/
|
|
1104
|
-
type
|
|
1105
|
-
|
|
1106
|
-
|
|
1062
|
+
type OptionalKeys<T extends object, V extends any = any> = {
|
|
1063
|
+
[K in keyof T]-?: {} extends {
|
|
1064
|
+
[P in K]: T[K];
|
|
1065
|
+
} ? V extends T[K] ? K : never : never;
|
|
1066
|
+
}[keyof T];
|
|
1107
1067
|
/**
|
|
1108
|
-
*
|
|
1068
|
+
* The _keys_ on a given object `T` which have a literal value of `W`.
|
|
1069
|
+
*
|
|
1070
|
+
* Optionally, you may provide a generic `E` to exclude certain keys in
|
|
1071
|
+
* result set.
|
|
1109
1072
|
* ```ts
|
|
1110
|
-
* // "
|
|
1111
|
-
* type
|
|
1073
|
+
* // "foo"
|
|
1074
|
+
* type Str = KeysWithValue<{ foo: "hi"; bar: 5 }>;
|
|
1112
1075
|
* ```
|
|
1113
|
-
*
|
|
1114
|
-
* _Intended to be used as a lower level utility; prefer `Dasherize<T>` for more full-fledged
|
|
1115
|
-
* dash solution_.
|
|
1116
1076
|
*/
|
|
1117
|
-
type
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
type OneToMany = `1:M`;
|
|
1121
|
-
type OneToZero = `1:0`;
|
|
1122
|
-
type ZeroToOne = `0:1`;
|
|
1123
|
-
type ZeroToMany = `0:M`;
|
|
1124
|
-
type ZeroToZero = `0:0`;
|
|
1125
|
-
type ManyToMany = "M:M";
|
|
1126
|
-
type ManyToOne = "M:1";
|
|
1127
|
-
type ManyToZero = "M:0";
|
|
1128
|
-
type CardinalityNode = "0" | "1" | "M";
|
|
1077
|
+
type KeysWithValue<W extends any, T extends object> = {
|
|
1078
|
+
[K in keyof T]: T[K] extends W ? Readonly<K> : never;
|
|
1079
|
+
}[keyof T];
|
|
1129
1080
|
/**
|
|
1130
|
-
*
|
|
1131
|
-
*
|
|
1132
|
-
*
|
|
1133
|
-
* Note: choose `CardinalityFilter1` if you want to allow output
|
|
1134
|
-
* to have no outputs.
|
|
1081
|
+
* A `PrivateKey` must start with a `_` character and then follow with
|
|
1082
|
+
* an alphabetic character
|
|
1135
1083
|
*/
|
|
1136
|
-
type
|
|
1084
|
+
type PrivateKey = `_${Alpha}${string}`;
|
|
1137
1085
|
/**
|
|
1138
|
-
*
|
|
1139
|
-
*
|
|
1086
|
+
* Keys on an object which have a `_` character as first part of the
|
|
1087
|
+
* name are considered private and this utility will create a union
|
|
1088
|
+
* of all the keys in this category.
|
|
1140
1089
|
*/
|
|
1141
|
-
type
|
|
1090
|
+
type PrivateKeys<T extends object> = {
|
|
1091
|
+
[K in keyof T]: K extends `_${string}` ? K : never;
|
|
1092
|
+
}[keyof T];
|
|
1142
1093
|
/**
|
|
1143
|
-
*
|
|
1144
|
-
*
|
|
1094
|
+
* **PublicKeys**
|
|
1095
|
+
*
|
|
1096
|
+
* Builds a union type of all keys which are "public" where a public
|
|
1097
|
+
* key is any key which _does not_ start with the `_` character.
|
|
1145
1098
|
*/
|
|
1146
|
-
type
|
|
1099
|
+
type PublicKeys<T extends object> = {
|
|
1100
|
+
[K in keyof T]: K extends `_${string}` ? never : K;
|
|
1101
|
+
}[keyof T];
|
|
1102
|
+
type StringKeys<T extends object> = {
|
|
1103
|
+
[K in keyof T]: K extends string ? Readonly<K> : never;
|
|
1104
|
+
}[keyof T];
|
|
1147
1105
|
/**
|
|
1148
|
-
*
|
|
1149
|
-
* _undefined_ -- and maps to 0,
|
|
1150
|
-
* 1, or many outputs.
|
|
1106
|
+
* The keys of an object which _are not_ a string type
|
|
1151
1107
|
*/
|
|
1152
|
-
type
|
|
1153
|
-
|
|
1108
|
+
type NonStringKeys<T extends object> = {
|
|
1109
|
+
[K in keyof T]: K extends string ? never : Readonly<K>;
|
|
1110
|
+
}[keyof T];
|
|
1111
|
+
type NumericKeys<T extends object> = {
|
|
1112
|
+
[K in keyof T]: K extends number ? Readonly<K> : never;
|
|
1113
|
+
}[keyof T];
|
|
1114
|
+
type NonNumericKeys<T extends object> = {
|
|
1115
|
+
[K in keyof T]: K extends number ? never : Readonly<K>;
|
|
1116
|
+
}[keyof T];
|
|
1154
1117
|
/**
|
|
1155
|
-
*
|
|
1118
|
+
* **RequiredProps**
|
|
1119
|
+
*
|
|
1120
|
+
* Reduces an object type to only key/value pairs where the key is required
|
|
1156
1121
|
*/
|
|
1157
|
-
type
|
|
1158
|
-
type CardinalityTuple<T extends Cardinality> = UnionToTuple<T>;
|
|
1122
|
+
type RequiredProps<T extends object> = Pick<T, RequiredKeys<T>>;
|
|
1159
1123
|
/**
|
|
1160
|
-
*
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
/**
|
|
1164
|
-
* The second or _output_ part of the Cardinality relationship
|
|
1124
|
+
* **OptionalProps**
|
|
1125
|
+
*
|
|
1126
|
+
* Reduces an object to only key/value pairs where the key is optional
|
|
1165
1127
|
*/
|
|
1166
|
-
type
|
|
1167
|
-
type CardinalityInput<T, C extends Cardinality> = CardinalityTuple<C>[0] extends 0 ? T | undefined : CardinalityTuple<C>[0] extends 1 ? T : T[];
|
|
1168
|
-
|
|
1128
|
+
type OptionalProps<T extends object> = Pick<T, OptionalKeys<T>>;
|
|
1169
1129
|
/**
|
|
1170
|
-
*
|
|
1130
|
+
* **WithValue**
|
|
1171
1131
|
*
|
|
1132
|
+
* Reduces an object's type down to only those key/value pairs where the
|
|
1133
|
+
* value is of type `W`.
|
|
1172
1134
|
* ```ts
|
|
1173
|
-
*
|
|
1174
|
-
*
|
|
1175
|
-
* type
|
|
1176
|
-
* type Dash = Dasherize<"FooBar">;
|
|
1177
|
-
* // "\n foo-bar \t"
|
|
1178
|
-
* type Dash = Dasherize<"\n foo bar \t">;
|
|
1135
|
+
* const foo = { a: 1, b: "hi", c: () => "hello" }
|
|
1136
|
+
* // { c: () => "hello" }
|
|
1137
|
+
* type W = WithValue<Function, typeof foo>
|
|
1179
1138
|
* ```
|
|
1180
1139
|
*/
|
|
1181
|
-
type
|
|
1182
|
-
|
|
1140
|
+
type WithValue<W extends any, T extends object, E extends any = undefined> = undefined extends E ? Pick<T, KeysWithValue<W, T>> : Omit<Pick<T, KeysWithValue<W, T>>, KeysWithValue<E, T>>;
|
|
1141
|
+
type DictionaryWithoutValue<TDict extends object, TWithoutValue> = Omit<TDict, KeysWithValue<TWithoutValue, TDict>>;
|
|
1183
1142
|
/**
|
|
1184
|
-
*
|
|
1185
|
-
*
|
|
1186
|
-
* // true
|
|
1187
|
-
* type T2 = IsCapitalized<"One">;
|
|
1188
|
-
* // false
|
|
1189
|
-
* type T1 = IsCapitalized<"one">;
|
|
1190
|
-
* // "unknown"
|
|
1191
|
-
* const a: string = "Hi";
|
|
1192
|
-
* type T3 = IsCapitalized<typeof a>;
|
|
1193
|
-
* ```
|
|
1194
|
-
*
|
|
1195
|
-
* Note: _if the value passed in is a "string" then the result will be "unknown"_
|
|
1143
|
+
* Reduces an object to only the key/value pairs where the key is a
|
|
1144
|
+
* string.
|
|
1196
1145
|
*/
|
|
1197
|
-
type
|
|
1198
|
-
|
|
1199
|
-
/**
|
|
1200
|
-
* **KebabCase<T>** is an _alias_ for **Dasherize<T>**.
|
|
1201
|
-
* ```ts
|
|
1202
|
-
* // "foo-bar"
|
|
1203
|
-
* type Kebab = KebabCase<"foo_bar">;
|
|
1204
|
-
* type Kebab = KebabCase<"fooBar">;
|
|
1205
|
-
* type Kebab = KebabCase<"FooBar">;
|
|
1206
|
-
* // "\n foo-bar \t"
|
|
1207
|
-
* type Kebab = KebabCase<"\n foo bar \t">;
|
|
1208
|
-
* ``` */
|
|
1209
|
-
type KebabCase<T extends string> = Dasherize<T>;
|
|
1210
|
-
|
|
1211
|
-
type Consonant = "b" | "c" | "d" | "f" | "g" | "h" | "j" | "k" | "l" | "m" | "n" | "p" | "q" | "r" | "s" | "t" | "v" | "w" | "x" | "z" | "y";
|
|
1212
|
-
type Exceptions = "photo => photos" | "piano => pianos" | "halo => halos" | "foot => feet" | "man => men" | "woman => women" | "person => people" | "mouse => mice" | "series => series" | "sheep => sheep" | "money => monies" | "deer => deer";
|
|
1213
|
-
type SingularException<T = Exceptions> = T extends `${infer SINGULAR} => ${infer PLURAL}` ? SINGULAR : never;
|
|
1214
|
-
type PluralException<T extends SingularException, E extends Exceptions = Exceptions> = E extends `${T} => ${infer PLURAL}` ? PLURAL : never;
|
|
1215
|
-
type SingularNoun = "s" | "sh" | "ch" | "x" | "z" | "o";
|
|
1216
|
-
type F = "f" | "fe";
|
|
1217
|
-
type Y = `${Consonant}y`;
|
|
1218
|
-
type RemoveTrailingY<T> = T extends `${infer HEAD}y` ? HEAD : T;
|
|
1219
|
-
/** validates that a word ends with a pluralization exception */
|
|
1220
|
-
type isException<T extends string> = T extends SingularException ? T : never;
|
|
1221
|
-
/** validates that a string literal ends in "is" */
|
|
1222
|
-
type EndsIn_IS<T extends string> = T extends `${infer HEAD}is` ? T : never;
|
|
1223
|
-
/** validates that a string literal is a singular noun */
|
|
1224
|
-
type EndsInSingularNoun<T extends string> = T extends `${infer HEAD}${SingularNoun}` ? T : never;
|
|
1225
|
-
/** validates that a string literal ends in "f" or "fe" */
|
|
1226
|
-
type EndsIn_F<T extends string> = T extends `${infer HEAD}${F}` ? T : never;
|
|
1227
|
-
/** validates that a string literal ends a consonant followed by "y" */
|
|
1228
|
-
type EndsIn_Y<T extends string> = T extends `${infer HEAD}${Y}` ? T : never;
|
|
1146
|
+
type WithStringKeys<T extends object> = Omit<T, NonStringKeys<T>>;
|
|
1229
1147
|
/**
|
|
1230
|
-
*
|
|
1148
|
+
* Reduces an object to only the key/value pairs where the key is numeric.
|
|
1231
1149
|
*/
|
|
1232
|
-
type
|
|
1150
|
+
type WithNumericKeys<T extends object> = Omit<T, NonNumericKeys<T>>;
|
|
1151
|
+
|
|
1233
1152
|
/**
|
|
1234
|
-
*
|
|
1153
|
+
* **Transformer**
|
|
1154
|
+
*
|
|
1155
|
+
* A function responsible for transforming the _values_ of
|
|
1156
|
+
* dictionary `I` into different _values_ for dictionary `O`.
|
|
1157
|
+
*
|
|
1158
|
+
* This type utility assumes that _keys_ of both dictionaries
|
|
1159
|
+
* are the same.
|
|
1235
1160
|
*/
|
|
1236
|
-
type
|
|
1161
|
+
type Transformer<I extends object, O extends SameKeys<I>, K extends keyof I = keyof I> = (input: I, key: K) => O[K];
|
|
1162
|
+
|
|
1237
1163
|
/**
|
|
1238
|
-
*
|
|
1164
|
+
* Takes a dictionary of type `I` and converts it to a dictionary of type `O` where
|
|
1165
|
+
* they _keys_ used in both dictionaries are the same.
|
|
1166
|
+
*
|
|
1167
|
+
* The _transform_ function passed in must be able to recieve the full input object
|
|
1168
|
+
* and key, and then return expected value of `O` for the given key.
|
|
1239
1169
|
*/
|
|
1240
|
-
|
|
1170
|
+
declare function dictionaryTransform<I extends object, O extends SameKeys<I>>(input: I, transform: Transformer<I, O>): O;
|
|
1171
|
+
|
|
1172
|
+
interface Uniqueness<T> {
|
|
1173
|
+
/** boolean flag to indicate whether the property was unique across all records */
|
|
1174
|
+
isUnique: boolean;
|
|
1175
|
+
/** the overall number of records which contained the property */
|
|
1176
|
+
size: number;
|
|
1177
|
+
/** specifies if undefined values were encountered for this property */
|
|
1178
|
+
includedUndefined: boolean;
|
|
1179
|
+
/** the unique values for the property across all records */
|
|
1180
|
+
values: readonly T[];
|
|
1181
|
+
}
|
|
1182
|
+
type DictArrApi<T extends Record<string, Narrowable>, A extends readonly T[]> = {
|
|
1183
|
+
length: number;
|
|
1184
|
+
toLookup<PL extends RequiredKeys<T, string> & keyof T & string>(prop: PL): UniqueForProp<A, PL> extends string ? Record<UniqueForProp<A, PL>, T> : Record<string, T>;
|
|
1185
|
+
sum<PS extends RequiredKeys<T, number> | OptionalKeys<T, number>>(prop: PS): number;
|
|
1186
|
+
count<PC extends OptionalKeys<T>>(prop: PC): number;
|
|
1187
|
+
unique<PU extends Keys<T> & keyof T>(prop: PU): Uniqueness<T[PU]>;
|
|
1188
|
+
};
|
|
1241
1189
|
/**
|
|
1242
|
-
*
|
|
1190
|
+
* converts an array of objects to a dictionary with keys formed from a given property
|
|
1191
|
+
* of the object and the value being the object itself.
|
|
1243
1192
|
*/
|
|
1244
|
-
|
|
1245
|
-
type Pluralize<T extends string> = T extends isException<T> ? PluralException<T> : T extends EndsIn_IS<T> ? PluralizeEndingIn_IS<T> : T extends EndsInSingularNoun<T> ? PluralizeEndingSingularNoun<T> : T extends EndsIn_F<T> ? PluralizeEnding_F<T> : T extends EndsIn_Y<T> ? PluralizeEndingIn_Y<T> : `${T}s`;
|
|
1193
|
+
declare const dictArr: <T extends Record<string, Narrowable>>(...dicts: readonly T[]) => DictArrApi<T, readonly T[]>;
|
|
1246
1194
|
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
* type T = SnakeCase<"fooBar">;
|
|
1254
|
-
* type T = SnakeCase<"FooBar">;
|
|
1255
|
-
* type T = SnakeCase<"foo-bar">;
|
|
1256
|
-
* type T = SnakeCase<"\n foo bar \t">;
|
|
1257
|
-
* ``` */
|
|
1258
|
-
type SnakeCase<S extends string> = string extends S ? string : DashUppercase<Uncapitalize<SpaceToDash<Trim<LowerAllCaps<S>>>>> extends `${infer Begin}${"-"}${infer Rest}` ? SnakeCase<`${Lowercase<Begin>}_${Rest}`> : Lowercase<DashUppercase<Uncapitalize<Trim<LowerAllCaps<S>>>>>;
|
|
1195
|
+
type DictFromKv<T extends readonly {
|
|
1196
|
+
key: string;
|
|
1197
|
+
value: unknown;
|
|
1198
|
+
}[]> = {
|
|
1199
|
+
[R in T[number] as R["key"]]: R["value"];
|
|
1200
|
+
};
|
|
1259
1201
|
|
|
1260
1202
|
/**
|
|
1261
|
-
*
|
|
1203
|
+
* Provides a strongly typed _key_ and _value_ for a dictionary `T`
|
|
1262
1204
|
*
|
|
1263
|
-
* Will strip off of `T` the starting string defined by `U` when
|
|
1264
|
-
* both are string literals.
|
|
1265
1205
|
* ```ts
|
|
1266
|
-
* type
|
|
1267
|
-
*
|
|
1268
|
-
*
|
|
1269
|
-
* type R = StripStarting<T,U>;
|
|
1206
|
+
* type Obj = { foo: 1, bar: "hi" };
|
|
1207
|
+
* // ["foo", 1 ]
|
|
1208
|
+
* type Foo = KeyValue<Obj, "foo">;
|
|
1270
1209
|
* ```
|
|
1271
1210
|
*/
|
|
1272
|
-
type
|
|
1211
|
+
type KeyValue<T extends object, K extends keyof T> = [K & keyof T, ExpandRecursively<T[K]>];
|
|
1273
1212
|
|
|
1274
1213
|
/**
|
|
1275
|
-
*
|
|
1276
|
-
*
|
|
1277
|
-
* Will strip off of `T` the ending defined by `U` when
|
|
1278
|
-
* both are string literals.
|
|
1214
|
+
* Type utility which takes an object type and converts to an array of KV objects:
|
|
1279
1215
|
* ```ts
|
|
1280
|
-
*
|
|
1281
|
-
* type
|
|
1282
|
-
* // "Hello"
|
|
1283
|
-
* type R = StripEnding<T,U>;
|
|
1216
|
+
* // [ {key: "id", value: 123 } | {key: "foo", value: "bar" } ][]
|
|
1217
|
+
* type Arr = KvFrom<{ id: 123, foo: "bar" }>;
|
|
1284
1218
|
* ```
|
|
1285
1219
|
*/
|
|
1286
|
-
type
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
*/
|
|
1293
|
-
type DomainName = `${AlphaNumeric}${string}.${AlphaNumeric}${string}` | `${AlphaNumeric}${string}.${AlphaNumeric}${string}.${string}` | `${AlphaNumeric}${string}.${AlphaNumeric}${string}.${string}.${string}`;
|
|
1294
|
-
type RelativeUrl = `${VariableName | "/"}`;
|
|
1295
|
-
/**
|
|
1296
|
-
* A literal variant of _string_ which forces a string to follow conventions
|
|
1297
|
-
* for a fully qualified URL like `https://google.com`. It can't ensure the
|
|
1298
|
-
* type is fully valid but does help to avoid some typos.
|
|
1299
|
-
*/
|
|
1300
|
-
type FullyQualifiedUrl = `${NetworkProtocol}://${Ipv4 | DomainName}/${string}`;
|
|
1301
|
-
type UrlBuilder = (<P extends NetworkProtocol, D extends DomainName, B extends RelativeUrl>(protocol: P, domain: D, basePath: B) => `${P}://${D}/${B}`) | (<U extends RelativeUrl>(url: U) => U);
|
|
1220
|
+
type KvFrom<T extends object> = Array<{
|
|
1221
|
+
[K in keyof T]: {
|
|
1222
|
+
key: K;
|
|
1223
|
+
value: T[K];
|
|
1224
|
+
};
|
|
1225
|
+
}[keyof T]>;
|
|
1302
1226
|
|
|
1303
1227
|
/**
|
|
1304
|
-
*
|
|
1305
|
-
*
|
|
1306
|
-
*
|
|
1228
|
+
* **KvTuple**
|
|
1229
|
+
*
|
|
1230
|
+
* a key/value of type `T` represented as `[key, kv]`
|
|
1231
|
+
*
|
|
1307
1232
|
* ```ts
|
|
1308
|
-
*
|
|
1309
|
-
*
|
|
1310
|
-
*
|
|
1311
|
-
* bye: (name: string) => `bye ${name}`
|
|
1312
|
-
* };
|
|
1313
|
-
* // { hi: string; bye: string }
|
|
1314
|
-
* type Test = UnwrapValue<typeof api>
|
|
1315
|
-
* // { val: number; foo: string; bar: string }
|
|
1316
|
-
* type Test2 = UnwrapValue<typeof api, false>
|
|
1233
|
+
* type Obj = { foo: 1, bar: "hi" };
|
|
1234
|
+
* // ["foo", { foo: 1 } ]
|
|
1235
|
+
* type Foo = KvTuple<Obj, "foo">;
|
|
1317
1236
|
* ```
|
|
1237
|
+
*
|
|
1238
|
+
* **Note:** _consider use of `KeyValue<T,K>` as an alternate representation_
|
|
1318
1239
|
*/
|
|
1319
|
-
type
|
|
1320
|
-
[K in keyof T]: T[K] extends (...args: any[]) => any ? Record<K, ReturnType<T[K]>> : true extends I ? never : Record<K, T[K]>;
|
|
1321
|
-
}[keyof T]>;
|
|
1240
|
+
type KvTuple<T, K extends keyof T> = [K, Record<K, T[K]>];
|
|
1322
1241
|
|
|
1323
1242
|
/**
|
|
1324
|
-
*
|
|
1325
|
-
* the original object `I` so long as the original value for the KV pair extends `V`.
|
|
1243
|
+
* **entries**
|
|
1326
1244
|
*
|
|
1327
|
-
*
|
|
1245
|
+
* Provides an _iterable_ over the passed in dictionary object where each iteration
|
|
1246
|
+
* provides a tuple of `[ key, value ]` which preserve type literals.
|
|
1328
1247
|
*
|
|
1248
|
+
* For example:
|
|
1329
1249
|
* ```ts
|
|
1330
|
-
*
|
|
1331
|
-
* //
|
|
1332
|
-
*
|
|
1333
|
-
* // { foo: number }
|
|
1334
|
-
* type StringToBool = DictChangeValue<Obj, boolean, string>
|
|
1250
|
+
* const obj = { foo: 1, bar: "hi" };
|
|
1251
|
+
* // k type is "foo" then "bar"; v type is 1 then "hi"
|
|
1252
|
+
* for (const [k, v] of entries(obj)) { ... }
|
|
1335
1253
|
* ```
|
|
1336
1254
|
*/
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
/** the return type that functions should be modified to have */
|
|
1341
|
-
T extends any,
|
|
1342
|
-
/**
|
|
1343
|
-
*The type we expect in the value; if the value extends type `V` then the value will
|
|
1344
|
-
* be converted to type `O`; if not then the KV pair will be discarded
|
|
1345
|
-
*/
|
|
1346
|
-
V extends any = any> = SimplifyObject<{
|
|
1347
|
-
[K in keyof I]: I[K] extends V ? Record<K, T> : never;
|
|
1348
|
-
}[keyof I]>;
|
|
1255
|
+
declare function entries<N extends Narrowable, T extends Record<string, N>, I extends KeyValue<T, keyof T>>(obj: T): {
|
|
1256
|
+
[Symbol.iterator](): Generator<I, void, unknown>;
|
|
1257
|
+
};
|
|
1349
1258
|
|
|
1350
1259
|
/**
|
|
1351
|
-
* **
|
|
1260
|
+
* **mapValues**
|
|
1352
1261
|
*
|
|
1353
|
-
*
|
|
1354
|
-
* arguments `<A>` and then return what had subsequently been the value of the property.
|
|
1262
|
+
* Maps over a dictionary, preserving the keys but allowing the values to be mutated.
|
|
1355
1263
|
*
|
|
1356
|
-
*
|
|
1357
|
-
*
|
|
1358
|
-
*
|
|
1264
|
+
* ```ts
|
|
1265
|
+
* const colors = { red: 4, blue: 2, green: 3 };
|
|
1266
|
+
* // { red: 8, blue: 4, green: 6 }
|
|
1267
|
+
* const twoX = mapValues(colors, v => v * 2);
|
|
1268
|
+
* ```
|
|
1359
1269
|
*/
|
|
1360
|
-
|
|
1361
|
-
[K in keyof T]: T[K] extends E ? Record<K, (...args: A) => T[K]> : Record<K, T[K]>;
|
|
1362
|
-
}[keyof T]>;
|
|
1270
|
+
declare function mapValues<N extends Narrowable, T extends Record<string, N>, V>(obj: T, valueMapper: (k: T[keyof T]) => V): { [K in keyof T]: V; };
|
|
1363
1271
|
|
|
1364
1272
|
/**
|
|
1365
|
-
*
|
|
1366
|
-
*
|
|
1367
|
-
* A type utility which receives an object `<T>` and then modifies
|
|
1368
|
-
* the return type of any properties which are a function to have this
|
|
1369
|
-
* new **ReturnType** `<R>`. Optionally you can specify a particular return type which
|
|
1370
|
-
* you are targeting and then
|
|
1273
|
+
* converts an array of strings `["a", "b", "c"]` into a more type friendly
|
|
1274
|
+
* dictionary of the type `{ a: true, b: true, c: true }`
|
|
1371
1275
|
*/
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1276
|
+
declare function strArrayToDict<T extends readonly string[]>(...strings: T): ExpandRecursively<Record<T[number], true>>;
|
|
1277
|
+
|
|
1278
|
+
/**
|
|
1279
|
+
* Converts a dictionary object into an array of dictionaries with `key` and `value` properties
|
|
1280
|
+
* ```ts
|
|
1281
|
+
* // [ { key: "id", value: 123 }, { key: "foo", value: "bar" } ]
|
|
1282
|
+
* const arr = dictToKv({ id: 123, foo: "bar" });
|
|
1283
|
+
* ```
|
|
1284
|
+
*/
|
|
1285
|
+
declare function dictToKv<N extends Narrowable, T extends {
|
|
1286
|
+
[key: string]: N;
|
|
1287
|
+
}, U extends boolean>(obj: T, _makeTuple?: U): U extends true ? UnionToTuple<(Mutable<T> extends infer T_1 extends object ? { [K in keyof T_1]: {
|
|
1288
|
+
key: K;
|
|
1289
|
+
value: Mutable<T>[K];
|
|
1290
|
+
}; } : never)[keyof T], LastInUnion<(Mutable<T> extends infer T_1 extends object ? { [K in keyof T_1]: {
|
|
1291
|
+
key: K;
|
|
1292
|
+
value: Mutable<T>[K];
|
|
1293
|
+
}; } : never)[keyof T]>> : KvFrom<Mutable<T>>;
|
|
1294
|
+
|
|
1295
|
+
type DictArrayFilterCallback<K extends keyof T, T extends object, R extends true | false> = (key: K, value: Pick<T, K>) => R;
|
|
1296
|
+
/**
|
|
1297
|
+
* An element in a `DictArray` shaped as a two element tuple: `[key, kv]`.
|
|
1298
|
+
*/
|
|
1299
|
+
type DictArrayKv<K extends keyof T, T> = [K, Pick<T, K>];
|
|
1300
|
+
type DictKvTuple<K extends string> = [K, Record<K, unknown>];
|
|
1301
|
+
/**
|
|
1302
|
+
* A an array of `DictArrayKv` tuples which can be reconstructed
|
|
1303
|
+
* to a strongly typed dictionary object.
|
|
1304
|
+
* ```ts
|
|
1305
|
+
* const example: DictArray<{ foo: 1, bar: "hi" }> = [
|
|
1306
|
+
* [ "foo", { foo: 1 }],
|
|
1307
|
+
* [ "bar", { bar: "hi" }]
|
|
1308
|
+
* ]
|
|
1309
|
+
* ```
|
|
1310
|
+
*/
|
|
1311
|
+
type DictArray<T> = Array<{
|
|
1312
|
+
[K in keyof T]: DictArrayKv<K, T>;
|
|
1380
1313
|
}[keyof T]>;
|
|
1381
1314
|
|
|
1382
1315
|
/**
|
|
1383
|
-
*
|
|
1316
|
+
* Returns the _first_ key in an object.
|
|
1317
|
+
*
|
|
1318
|
+
* **Note:** key order is not guarenteed so typically this is used
|
|
1319
|
+
* for a key/value pair where only one key is expected
|
|
1384
1320
|
*/
|
|
1385
|
-
type
|
|
1321
|
+
type FirstKey<T extends object> = UnionToTuple<Keys<T>>[0];
|
|
1386
1322
|
|
|
1387
|
-
declare const DEFAULT_ONE_TO_MANY_MAPPING: FinalizedMapConfig<"req", "I -> O[]", "opt">;
|
|
1388
|
-
declare const DEFAULT_ONE_TO_ONE_MAPPING: FinalizedMapConfig<"req", "I -> O", "req">;
|
|
1389
|
-
declare const DEFAULT_MANY_TO_ONE_MAPPING: FinalizedMapConfig<"req", "I[] -> O", "req">;
|
|
1390
|
-
type DefaultOneToManyMapping = typeof DEFAULT_ONE_TO_MANY_MAPPING;
|
|
1391
|
-
type DefaultOneToOneMapping = typeof DEFAULT_ONE_TO_ONE_MAPPING;
|
|
1392
|
-
type DefaultManyToOneMapping = typeof DEFAULT_MANY_TO_ONE_MAPPING;
|
|
1393
1323
|
/**
|
|
1394
|
-
* **
|
|
1324
|
+
* Utility type which operates on a dictionary and provides the **value** of the
|
|
1325
|
+
* `First<T>` key of the dictionary. Because dictionary's don't provide assurances
|
|
1326
|
+
* about key order, this is typically only used in cases where it's known there is
|
|
1327
|
+
* a single key on the object.
|
|
1328
|
+
*/
|
|
1329
|
+
type FirstKeyValue<T extends object> = FirstKey<T> extends keyof T ? T[FirstKey<T>] : never;
|
|
1330
|
+
|
|
1331
|
+
/**
|
|
1332
|
+
* For a two-dimensional array, returns a _union type_ which combines the first element of the interior
|
|
1333
|
+
* array.
|
|
1395
1334
|
*
|
|
1396
|
-
* This utility -- by default -- creates a strongly typed 1:M data mapper which maps from one
|
|
1397
|
-
* known source `I` to any array of another `O[]`:
|
|
1398
1335
|
* ```ts
|
|
1399
|
-
* const
|
|
1400
|
-
*
|
|
1401
|
-
*
|
|
1336
|
+
* const test = [ ["foo", 1], ["bar", 2] ];
|
|
1337
|
+
* // "foo" | "bar"
|
|
1338
|
+
* type F = FirstOfEach<typeof test>;
|
|
1402
1339
|
* ```
|
|
1403
1340
|
*/
|
|
1404
|
-
|
|
1341
|
+
type FirstOfEach<T extends readonly any[][]> = T[number][0] extends T[number][number] ? T[number][0] : never;
|
|
1342
|
+
|
|
1405
1343
|
/**
|
|
1406
|
-
*
|
|
1407
|
-
* and
|
|
1344
|
+
* Typescript utility which receives `T` as shape which resembles `DictArray<D>`
|
|
1345
|
+
* and if the type `D` can be inferred it is returned.
|
|
1346
|
+
* ```ts
|
|
1347
|
+
* // { foo: 1; bar: "hi" }
|
|
1348
|
+
* type Dict = FromDictArray<[["foo", { foo: 1 }], ["bar", { bar: "hi" }]]>;
|
|
1349
|
+
* ```
|
|
1408
1350
|
*/
|
|
1409
|
-
|
|
1351
|
+
type FromDictArray<T extends [string, Record<string, unknown>][]> = ExpandRecursively<UnionToIntersection<T[number][1]>>;
|
|
1352
|
+
|
|
1410
1353
|
/**
|
|
1411
|
-
*
|
|
1354
|
+
* For a two-dimensional array, returns a _union type_ which combines the first element of the interior
|
|
1355
|
+
* array.
|
|
1412
1356
|
*
|
|
1413
|
-
*
|
|
1414
|
-
*
|
|
1357
|
+
* ```ts
|
|
1358
|
+
* // 1 | 2
|
|
1359
|
+
* type F = SecondOfEach<[ ["foo", 1], ["bar", 2] ]>;
|
|
1360
|
+
* ```
|
|
1361
|
+
*/
|
|
1362
|
+
type SecondOfEach<T extends any[][]> = T[number][1] extends T[number][number] ? T[number][1] : never;
|
|
1363
|
+
|
|
1364
|
+
interface Array$1<T> {
|
|
1365
|
+
filter<U extends T>(pred: (a: T) => a is U): U[];
|
|
1366
|
+
}
|
|
1367
|
+
/**
|
|
1368
|
+
* Accepts a `DictArray` and a callback which receives each key
|
|
1369
|
+
* value pair.
|
|
1370
|
+
*/
|
|
1371
|
+
declare function filterDictArray<T extends object, C extends DictArrayFilterCallback<keyof T, T, true | false>>(dictArr: DictArray<T>, cb: C): DictArray<Omit<T, "">>;
|
|
1372
|
+
|
|
1373
|
+
/**
|
|
1374
|
+
* Build a key-value pair where both _key_ and _value_ are inferred. This
|
|
1375
|
+
* includes ensuring that the _key_ is a type literal not just a "string".
|
|
1415
1376
|
*
|
|
1416
|
-
*
|
|
1377
|
+
* > note: the value will be inferred but if you need to constrain it
|
|
1378
|
+
* > to a narrower type then both inferences will break and you should
|
|
1379
|
+
* > instead use `KV2` to get this capability.
|
|
1380
|
+
*/
|
|
1381
|
+
declare function kv<K extends string, N extends Narrowable, V extends Record<any, N> | boolean | number | string | null | undefined>(key: K, value: V): ExpandRecursively<Record<K, V>>;
|
|
1382
|
+
|
|
1383
|
+
/**
|
|
1384
|
+
* Converts an array of dictionaries with `key` and `value` properties to a singular dictionary.
|
|
1417
1385
|
* ```ts
|
|
1418
|
-
*
|
|
1419
|
-
* const
|
|
1420
|
-
* const one2one = mapTo.oneToOne().map<I,O>( ... );
|
|
1421
|
-
* const many2one = mapTo.manyToOne().map<I,O>( ... );
|
|
1386
|
+
* // { id: 123, foo: "bar" }
|
|
1387
|
+
* const arr = kvToDict([{ key: "id", value: 123 }, { key: "foo", value: "bar" }]);
|
|
1422
1388
|
* ```
|
|
1389
|
+
*
|
|
1390
|
+
* Note: this is the inverse of `dictToKv()` function
|
|
1423
1391
|
*/
|
|
1424
|
-
declare
|
|
1392
|
+
declare function kvToDict<K extends string, V extends Narrowable, T extends readonly Readonly<{
|
|
1393
|
+
key: K;
|
|
1394
|
+
value: V;
|
|
1395
|
+
}>[]>(kvArr: T): DictFromKv<T>;
|
|
1425
1396
|
|
|
1426
1397
|
/**
|
|
1427
|
-
*
|
|
1398
|
+
* Type utility which converts `undefined[]` to `unknown[]`
|
|
1428
1399
|
*/
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
OneToMany = "I -> O[]",
|
|
1432
|
-
/** every input results in 0:1 outputs */
|
|
1433
|
-
OneToOne = "I -> O",
|
|
1434
|
-
/** every input is an array of type I and reduced to a single O */
|
|
1435
|
-
ManyToOne = "I[] -> O"
|
|
1436
|
-
}
|
|
1437
|
-
type MapCardinalityIllustrated = EnumValues<MapCardinality>;
|
|
1400
|
+
type UndefinedArrayIsUnknown<T extends any[]> = undefined[] extends T ? unknown[] : T;
|
|
1401
|
+
type AsArray<T, W extends boolean = false> = T extends any[] ? W extends true ? Widen<T> : T : W extends true ? UndefinedArrayIsUnknown<Widen<T>[]> : UndefinedArrayIsUnknown<T[]>;
|
|
1438
1402
|
/**
|
|
1439
|
-
*
|
|
1440
|
-
*
|
|
1441
|
-
*
|
|
1403
|
+
* Ensures that any input passed in is passed back as an array:
|
|
1404
|
+
*
|
|
1405
|
+
* - if it was already an array than this just serves as an _identity_ function
|
|
1406
|
+
* - if it was not then it wraps the element into a one element array of the
|
|
1407
|
+
* given type
|
|
1408
|
+
*
|
|
1409
|
+
* Note: by default the _type_ of values will be intentionally widened so that the value "abc"
|
|
1410
|
+
* is of type `string` not the literal `abc`. If you want to keep literal types then
|
|
1411
|
+
* change the optional _widen_ parameter to _false_.
|
|
1442
1412
|
*/
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
output?: OR;
|
|
1446
|
-
cardinality?: D;
|
|
1447
|
-
/**
|
|
1448
|
-
* Whether calls to the final `MapFn` will be logged to stderr
|
|
1449
|
-
* for debugging purposes. Defaults to false; if you specify
|
|
1450
|
-
* a _string_ for a value that will be sent to stderr along
|
|
1451
|
-
* with other debugging info.
|
|
1452
|
-
*/
|
|
1453
|
-
debug?: boolean | string;
|
|
1454
|
-
}
|
|
1413
|
+
declare const asArray: <T extends Narrowable, W extends boolean = true>(thing: T, _widen?: W | undefined) => AsArray<T, W>;
|
|
1414
|
+
|
|
1455
1415
|
/**
|
|
1456
|
-
*
|
|
1457
|
-
*
|
|
1416
|
+
* Groups an array of data based on the value of a property
|
|
1417
|
+
* in the objects within the array.
|
|
1418
|
+
* ```ts
|
|
1419
|
+
* const data = [ {}, {}, {} ];
|
|
1458
1420
|
*
|
|
1459
|
-
*
|
|
1460
|
-
*
|
|
1421
|
+
* ```
|
|
1422
|
+
*
|
|
1423
|
+
* @ignore not implemented
|
|
1461
1424
|
*/
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
debug: boolean | string;
|
|
1465
|
-
};
|
|
1425
|
+
declare function groupBy<T extends Record<string, Narrowable>>(_data: Readonly<T[]>): void;
|
|
1426
|
+
|
|
1466
1427
|
/**
|
|
1467
|
-
*
|
|
1468
|
-
* cardinality already (e.g., `oneToMany()`, `manyToOne()`)
|
|
1428
|
+
* The basic shape of a `Converter`
|
|
1469
1429
|
*/
|
|
1470
|
-
type
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
/**
|
|
1476
|
-
* Whether calls to the final `MapFn` will be logged to stderr
|
|
1477
|
-
* for debugging purposes. Defaults to false; if you set to a string
|
|
1478
|
-
* value than this will be echoed out with stderr.
|
|
1479
|
-
*/
|
|
1480
|
-
debug?: boolean | string;
|
|
1430
|
+
type ConverterShape<S extends Narrowable, N extends Narrowable, B extends Narrowable, O extends Narrowable> = {
|
|
1431
|
+
string: <T extends string>(v: T) => S;
|
|
1432
|
+
number: <T extends number>(v: T) => N;
|
|
1433
|
+
boolean: <T extends boolean>(v: T) => B;
|
|
1434
|
+
object: <T extends Record<string, any>>(v: T) => O;
|
|
1481
1435
|
};
|
|
1436
|
+
type ConverterKeys<S, N, B, O> = UnionToTuple<Keys<DictionaryWithoutValue<{
|
|
1437
|
+
string: S;
|
|
1438
|
+
number: N;
|
|
1439
|
+
boolean: B;
|
|
1440
|
+
object: O;
|
|
1441
|
+
}, undefined>>>;
|
|
1442
|
+
type ConverterInputType<T extends string> = T extends "string" ? string : T extends "number" ? number : T extends "boolean" ? boolean : T extends "object" ? Record<string, any> : unknown;
|
|
1443
|
+
type ConverterInputUnion<TConverted extends readonly any[], TRemaining extends readonly string[]> = [] extends TRemaining ? TConverted : ConverterInputUnion<[
|
|
1444
|
+
...TConverted,
|
|
1445
|
+
ConverterInputType<First<TRemaining>>
|
|
1446
|
+
], AfterFirst<TRemaining>>;
|
|
1482
1447
|
/**
|
|
1483
|
-
* **
|
|
1448
|
+
* **AvailableConverters**
|
|
1484
1449
|
*
|
|
1485
|
-
*
|
|
1486
|
-
* configuration of the _inputs_ and _outputs_ and provides a `.map()`
|
|
1487
|
-
* method which allows the user configure the specifics of the mapping.
|
|
1450
|
+
* Type utility which will produce the correct union type for a "converter"
|
|
1488
1451
|
*/
|
|
1489
|
-
type
|
|
1490
|
-
|
|
1491
|
-
input: MapIR<C>;
|
|
1492
|
-
cardinality: MapCard<C>;
|
|
1493
|
-
output: MapOR<C>;
|
|
1494
|
-
debug: boolean | string;
|
|
1495
|
-
};
|
|
1452
|
+
type AvailableConverters<S, N, B, O> = ConverterKeys<S, N, B, O> extends readonly string[] ? TupleToUnion<ConverterInputUnion<[], ConverterKeys<S, N, B, O>>> : never;
|
|
1453
|
+
|
|
1496
1454
|
/**
|
|
1497
|
-
*
|
|
1455
|
+
* **createConverter**(mapper)
|
|
1456
|
+
*
|
|
1457
|
+
* A runtime utility which allows for the creation of a function which
|
|
1458
|
+
* receives multiple wide types (string, number, boolean, object) and then transform it
|
|
1459
|
+
* based on the "wide type" but while retaining the potentially narrow values passed in.
|
|
1460
|
+
*
|
|
1461
|
+
* The number of wide types which the converter will accept is based on how it configured
|
|
1462
|
+
* as there are discrete functions which must be passed in for handling: strings, numbers,
|
|
1463
|
+
* booleans, and "objects" (aka, Record<string,any>).
|
|
1464
|
+
*
|
|
1465
|
+
* ```ts
|
|
1466
|
+
* // handles strings and numbers
|
|
1467
|
+
* const convert = createConverter({
|
|
1468
|
+
* string: s => `the string was ${s}`,
|
|
1469
|
+
* number: n => `the number was ${n}`,
|
|
1470
|
+
* });
|
|
1471
|
+
* ```
|
|
1498
1472
|
*/
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
type
|
|
1473
|
+
declare function createConverter<S extends Narrowable = undefined, N extends Narrowable = undefined, B extends Narrowable = undefined, O extends Narrowable = undefined>(mapper: Partial<ConverterShape<S, N, B, O>>): <T extends AvailableConverters<S, N, B, O>>(input: T) => Widen<T> extends string ? S : Widen<Not<T, string>> extends number ? N : Widen<Not<Not<T, string>, number>> extends boolean ? B : Widen<Not<Not<Not<T, string>, number>, boolean>> extends {} ? O : unknown;
|
|
1474
|
+
|
|
1475
|
+
type ExplicitFunction<P extends any[], R extends any> = (...args: P) => R;
|
|
1502
1476
|
/**
|
|
1503
|
-
*
|
|
1477
|
+
* Takes a given function and converts it to an explicit representation
|
|
1478
|
+
* where the generics represent the _parameter_ and _return_ typings.
|
|
1504
1479
|
*/
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
type MapOR<T extends FinalizedMapConfig<OptRequired, MapCardinalityIllustrated, OptRequired>> = DecomposeMapConfig<T>[2];
|
|
1480
|
+
declare function ExplicitFunction<T extends (...args: any[]) => any>(fn: T): ExplicitFunction<Parameters<T>, ReturnType<T>>;
|
|
1481
|
+
|
|
1508
1482
|
/**
|
|
1509
|
-
*
|
|
1483
|
+
* **UniqueDictionary**
|
|
1484
|
+
*
|
|
1485
|
+
* A dictionary converted by `arrayToObject()` which expects each key `S` to have a only a
|
|
1486
|
+
* single/unique value.
|
|
1510
1487
|
*/
|
|
1511
|
-
type
|
|
1512
|
-
|
|
1513
|
-
/**
|
|
1514
|
-
* Provides opportunity to configure _input_, _output_, and _cardinality_
|
|
1515
|
-
* prior to providing a mapping function.
|
|
1516
|
-
*
|
|
1517
|
-
* Note: _the defaults for configuration are defined by the_ `DEFAULT_ONE_TO_MANY_MAPPING`
|
|
1518
|
-
* _constant made available as a symbol from this library._
|
|
1519
|
-
*/
|
|
1520
|
-
config: <C extends MapConfig<OptRequired, //
|
|
1521
|
-
MapCardinalityIllustrated, OptRequired>>(config: C) => ConfiguredMap<AsFinalizedConfig<C, //
|
|
1522
|
-
DefaultOneToManyMapping>>;
|
|
1523
|
-
/**
|
|
1524
|
-
* Provides a nice 1:1 ratio between the input and output.
|
|
1525
|
-
*
|
|
1526
|
-
* By default the input and output are considered to be _required_
|
|
1527
|
-
* properties but this can be changed with the options hash provided.
|
|
1528
|
-
* ```ts
|
|
1529
|
-
* const mapper = mapTo.oneToOne().map(...);
|
|
1530
|
-
* // add in ability to filter out some inputs
|
|
1531
|
-
* const mapAndFilter = mapTo.oneToOne({ output: "opt" })
|
|
1532
|
-
* ```
|
|
1533
|
-
*/
|
|
1534
|
-
oneToOne: <C extends MapCardinalityConfig<OptRequired, OptRequired>>(config?: C) => ConfiguredMap<AsFinalizedConfig<C, //
|
|
1535
|
-
DefaultOneToOneMapping>>;
|
|
1536
|
-
/**
|
|
1537
|
-
* **manyToOne** _mapping_
|
|
1538
|
-
*
|
|
1539
|
-
* Provides a configuration where multiple inputs `I[]` will be mapped to a
|
|
1540
|
-
* single output `O`.
|
|
1541
|
-
*
|
|
1542
|
-
* Choosing this configuration will, by default, set both input and output
|
|
1543
|
-
* to be "required" but you can change this default if you so choose.
|
|
1544
|
-
*/
|
|
1545
|
-
manyToOne: <C extends MapCardinalityConfig<OptRequired | undefined, //
|
|
1546
|
-
//
|
|
1547
|
-
OptRequired | undefined>>(config?: C) => ConfiguredMap<AsFinalizedConfig<C, //
|
|
1548
|
-
DefaultManyToOneMapping>>;
|
|
1549
|
-
oneToMany: <C extends MapCardinalityConfig<OptRequired | undefined, //
|
|
1550
|
-
//
|
|
1551
|
-
OptRequired | undefined>>(config?: C) => ConfiguredMap<AsFinalizedConfig<C, //
|
|
1552
|
-
DefaultOneToManyMapping>>;
|
|
1488
|
+
type UniqueDictionary<S extends PropertyKey, N extends Narrowable, T extends Record<keyof T, N> & Record<S, any>> = {
|
|
1489
|
+
[V in T as V[S]]: V;
|
|
1553
1490
|
};
|
|
1554
|
-
type MapInput<I, //
|
|
1555
|
-
IR extends OptRequired, C extends MapCardinalityIllustrated> = C extends MapCardinality.OneToMany | "I -> O[]" ? IR extends "opt" ? I | undefined : I : C extends MapCardinality.OneToOne | "I -> O" ? IR extends "opt" ? I | undefined : I : C extends MapCardinality.ManyToOne | "I[] -> O" ? IR extends "opt" ? I[] | undefined : I[] : never;
|
|
1556
|
-
type MapOutput<O, //
|
|
1557
|
-
OR extends OptRequired, C extends MapCardinalityIllustrated> = C extends MapCardinality.OneToMany | "I -> O[]" ? OR extends "opt" ? O[] : [O, ...O[]] : C extends MapCardinality.OneToOne | "I -> O" ? OR extends "opt" ? O | null : O : C extends MapCardinality.ManyToOne | "I[] -> O" ? OR extends "opt" ? O | null : O : never;
|
|
1558
1491
|
/**
|
|
1559
|
-
* **
|
|
1560
|
-
*
|
|
1561
|
-
* A mapping function between an input type `I` and output type `O`. Defaults to using
|
|
1562
|
-
* the _default_ OneToMany mapping config.
|
|
1492
|
+
* **GeneralDictionary**
|
|
1563
1493
|
*
|
|
1564
|
-
*
|
|
1565
|
-
*
|
|
1494
|
+
* A dictionary converted by `arrayToObject()` which expects each key `S` to have an
|
|
1495
|
+
* array of values.
|
|
1566
1496
|
*/
|
|
1567
|
-
type
|
|
1568
|
-
|
|
1569
|
-
|
|
1497
|
+
type GeneralDictionary<S extends PropertyKey, N extends Narrowable, T extends Record<keyof T, N> & Record<S, any>> = {
|
|
1498
|
+
[V in T as V[S]]: V[];
|
|
1499
|
+
};
|
|
1500
|
+
type ArrayConverter<S extends PropertyKey, U extends boolean> =
|
|
1570
1501
|
/**
|
|
1571
|
-
*
|
|
1572
|
-
*
|
|
1573
|
-
*
|
|
1574
|
-
* 1. Iterative:
|
|
1575
|
-
* ```ts
|
|
1576
|
-
* const m = mapTo<I,O>(i => [ ... ]);
|
|
1577
|
-
* // maps inputs to outputs
|
|
1578
|
-
* const out = inputs.map(m);
|
|
1579
|
-
* ```
|
|
1580
|
-
* 2. Block:
|
|
1581
|
-
* ```ts
|
|
1582
|
-
* // maps inputs to outputs (filtering or splitting where appr.)
|
|
1583
|
-
* const out2 = m(inputs);
|
|
1584
|
-
* ```
|
|
1502
|
+
* An `ArrayConverter` is the partial application of the `arrayToObject()`
|
|
1503
|
+
* utility. At this point, the configuration is setup already and all that's
|
|
1504
|
+
* left is to pass in an array of objects.
|
|
1585
1505
|
*/
|
|
1586
|
-
|
|
1506
|
+
<N extends Narrowable, T extends Record<keyof T, N> & Record<S, any>>(arr: readonly T[]) => true extends U ? UniqueDictionary<S, N, T> : GeneralDictionary<S, N, T>;
|
|
1587
1507
|
/**
|
|
1588
|
-
*
|
|
1508
|
+
* Converts an array of objects into a dictionary by picking a property name contained
|
|
1509
|
+
* by all objects and using that as the key to the dictionary.
|
|
1589
1510
|
*
|
|
1590
|
-
* A fully configured _mapper_ stemming from the **mapTo()** utility. It is both a mapping
|
|
1591
|
-
* function and a dictionary which describes the mapper's properties.
|
|
1592
1511
|
* ```ts
|
|
1593
|
-
* const
|
|
1594
|
-
*
|
|
1595
|
-
*
|
|
1512
|
+
* const arr = [
|
|
1513
|
+
* { kind: "color", favorite: "blue", likes: 100 },
|
|
1514
|
+
* { kind: "song", favorite: "some song", likes: 25 }
|
|
1515
|
+
* ];
|
|
1516
|
+
* const dict = arrayToObject("kind")(arr);
|
|
1596
1517
|
* ```
|
|
1597
1518
|
*
|
|
1598
|
-
*
|
|
1599
|
-
* this is combined with a dictionary of settings and types
|
|
1600
|
-
* which you can use. For instance, look at the `fnSignature`
|
|
1601
|
-
* property to get the _type_ signature of the map function.
|
|
1519
|
+
* This will produce a dictionary with keys of `color` and `song`.
|
|
1602
1520
|
*/
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
inputType: I;
|
|
1609
|
-
outputType: O;
|
|
1610
|
-
/**
|
|
1611
|
-
* Provides the _type_ information for mapper function.
|
|
1612
|
-
*
|
|
1613
|
-
* Note: _this is just a **type**_ not the actual function which positioned
|
|
1614
|
-
* at the root of the Mapper type
|
|
1615
|
-
*/
|
|
1616
|
-
fnSignature: MapFn<I, O, C>;
|
|
1617
|
-
} & MapFn<I, O, C>;
|
|
1521
|
+
declare function arrayToObject<S extends PropertyKey, U extends boolean>(prop: S, unique?: U): ArrayConverter<S, true extends U ? true : false>;
|
|
1522
|
+
|
|
1523
|
+
declare function ifSameType<TValue extends Narrowable, TType extends string | number | boolean | object, IF extends Narrowable, ELSE extends Narrowable>(value: TValue, comparisonType: TType, ifExtends: <T extends TType & TValue>(v: T) => IF, doesNotExtend: (v: Not<TValue, TType>) => ELSE): Widen<TValue> extends Widen<TType> ? IF : ELSE;
|
|
1524
|
+
|
|
1525
|
+
declare function isArray<T>(i: T): IsArray<T>;
|
|
1618
1526
|
/**
|
|
1619
|
-
* **
|
|
1527
|
+
* **ifArray**(T, IF, ELSE)
|
|
1620
1528
|
*
|
|
1621
|
-
*
|
|
1529
|
+
* A utility which evaluates a type `T` for whether it is an array and then
|
|
1622
1530
|
*/
|
|
1623
|
-
|
|
1531
|
+
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>;
|
|
1532
|
+
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>;
|
|
1533
|
+
|
|
1624
1534
|
/**
|
|
1625
|
-
*
|
|
1626
|
-
*
|
|
1627
|
-
* Type utility which extracts the output [`O`] type from a fully configured `Mapper`
|
|
1535
|
+
* Runtime and type checks whether a variable is a boolean value.
|
|
1628
1536
|
*/
|
|
1629
|
-
|
|
1537
|
+
declare function isBoolean<T extends Narrowable>(i: T): IsBoolean<T>;
|
|
1630
1538
|
/**
|
|
1631
|
-
* **
|
|
1539
|
+
* **ifBoolean**
|
|
1632
1540
|
*
|
|
1633
|
-
*
|
|
1541
|
+
* Strongly type-aware conditional statement which checks whether a value is
|
|
1542
|
+
* a _boolean_ and returns one of two values (strongly typed) based on the evaluation
|
|
1543
|
+
* of this criteria.
|
|
1544
|
+
*
|
|
1545
|
+
* @param val the value being tested
|
|
1546
|
+
* @param ifVal the value (strongly typed) returned if val is _boolean_
|
|
1547
|
+
* @param elseVal the value (strongly typed) returned if val is NOT a _boolean
|
|
1634
1548
|
*/
|
|
1635
|
-
|
|
1549
|
+
declare function ifBoolean<T, IF, ELSE>(val: T, ifVal: IF, elseVal: ELSE): IsBoolean<T> extends true ? IF : ELSE;
|
|
1636
1550
|
|
|
1551
|
+
declare function isFalse<T>(i: T): IsFalse<T>;
|
|
1637
1552
|
/**
|
|
1638
|
-
*
|
|
1639
|
-
* make the `<M>` generic property _mutable_ and all other _read-only_.
|
|
1553
|
+
* **ifTrue**
|
|
1640
1554
|
*
|
|
1641
|
-
*
|
|
1642
|
-
*
|
|
1643
|
-
*
|
|
1644
|
-
*
|
|
1645
|
-
*
|
|
1646
|
-
*
|
|
1647
|
-
*
|
|
1555
|
+
* Strongly type-aware conditional statement which checks whether a value is
|
|
1556
|
+
* a _true_ and returns one of two values (strongly typed) based on the evaluation
|
|
1557
|
+
* of this criteria.
|
|
1558
|
+
*
|
|
1559
|
+
* @param val the value being tested
|
|
1560
|
+
* @param ifVal the value (strongly typed) returned if val is _true_ value
|
|
1561
|
+
* @param elseVal the value (strongly typed) returned if val is NOT a _true_ value
|
|
1562
|
+
*
|
|
1563
|
+
* Note: at runtime there's no way to distinguish if the value was widely or loosely
|
|
1564
|
+
* typed so unlike the type utility there is no "MAYBE" state but if a wide type if
|
|
1565
|
+
* encountered the _type_ will the union of `IF` and `ELSE`.
|
|
1648
1566
|
*/
|
|
1649
|
-
|
|
1567
|
+
declare function ifFalse<T extends boolean, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifVal: IF, elseVal: ELSE): IfFalse<T, IF, ELSE, IF | ELSE>;
|
|
1650
1568
|
|
|
1569
|
+
type IsFunction<T> = T extends FunctionType ? true : false;
|
|
1570
|
+
type HybridFunction<TProps extends {}> = (<TArgs extends any[]>(...args: TArgs) => any) & TProps;
|
|
1571
|
+
type SimpleFunction = (...args: any[]) => any;
|
|
1572
|
+
type AnyFunction<TProps extends {} = {}> = SimpleFunction | HybridFunction<TProps>;
|
|
1651
1573
|
/**
|
|
1652
|
-
*
|
|
1653
|
-
*
|
|
1654
|
-
* more than one prop required).
|
|
1655
|
-
*
|
|
1574
|
+
* Checks whether a passed in value is a function and ensures run-time and types
|
|
1575
|
+
* are consistent.
|
|
1656
1576
|
* ```ts
|
|
1657
|
-
* //
|
|
1658
|
-
*
|
|
1577
|
+
* // true
|
|
1578
|
+
* const yup = isFunction(() => "hello world");
|
|
1659
1579
|
* ```
|
|
1580
|
+
*
|
|
1581
|
+
* Note: the runtime `typeof [variable]` will correctly say "function" when a function is
|
|
1582
|
+
* encountered but if that function also has object types defined then the type will be a big
|
|
1583
|
+
* and ugly union type. This function will give you a proper boolean value in both cases.
|
|
1660
1584
|
*/
|
|
1661
|
-
|
|
1585
|
+
declare function isFunction<T>(input: T): IsFunction<T>;
|
|
1662
1586
|
|
|
1587
|
+
type IsNull<T> = T extends null ? true : false;
|
|
1588
|
+
declare function isNull<T extends Narrowable>(i: T): T extends null ? true : false;
|
|
1663
1589
|
/**
|
|
1664
|
-
* **
|
|
1590
|
+
* **ifNull**
|
|
1665
1591
|
*
|
|
1666
|
-
*
|
|
1667
|
-
*
|
|
1592
|
+
* Strongly type-aware conditional statement which checks whether a value is
|
|
1593
|
+
* Null and returns one of two values (strongly typed) based on the evaluation
|
|
1594
|
+
* of this criteria.
|
|
1668
1595
|
*
|
|
1669
|
-
*
|
|
1670
|
-
*
|
|
1596
|
+
* @param val the value being tested
|
|
1597
|
+
* @param ifVal the value (strongly typed) returned if val is `null`
|
|
1598
|
+
* @param elseVal the value (strongly typed) returned if val is NOT `null`
|
|
1671
1599
|
*/
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
} & X;
|
|
1600
|
+
declare function ifNull<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifVal: IF, elseVal: ELSE): IsNull<T> extends true ? IF : ELSE;
|
|
1601
|
+
|
|
1602
|
+
type IsNumber<T> = T extends number ? true : false;
|
|
1603
|
+
declare function isNumber<T>(i: T): T extends number ? true : false;
|
|
1677
1604
|
/**
|
|
1678
|
-
*
|
|
1679
|
-
* which returns the same API surface.
|
|
1605
|
+
* **ifNumber**
|
|
1680
1606
|
*
|
|
1681
|
-
*
|
|
1682
|
-
*
|
|
1683
|
-
*
|
|
1607
|
+
* Strongly type-aware conditional statement which checks whether a value is
|
|
1608
|
+
* a _number_ and returns one of two values (strongly typed) based on the evaluation
|
|
1609
|
+
* of this criteria.
|
|
1684
1610
|
*
|
|
1685
|
-
*
|
|
1686
|
-
*
|
|
1611
|
+
* @param val the value being tested
|
|
1612
|
+
* @param ifVal the value (strongly typed) returned if val is number
|
|
1613
|
+
* @param elseVal the value (strongly typed) returned if val is NOT a number
|
|
1687
1614
|
*/
|
|
1688
|
-
|
|
1689
|
-
[P in keyof TApi]: (...args: Parameters<TApi[P]>) => PureFluentApi<Omit<TApi, TExclude>>;
|
|
1690
|
-
};
|
|
1615
|
+
declare function ifNumber<T, IF, ELSE>(val: T, ifVal: IF, elseVal: ELSE): IsNumber<T> extends true ? IF : ELSE;
|
|
1691
1616
|
|
|
1617
|
+
type ObjectType = Not<Record<string, Narrowable>, FunctionType>;
|
|
1692
1618
|
/**
|
|
1693
|
-
*
|
|
1694
|
-
* to
|
|
1695
|
-
*
|
|
1696
|
-
*
|
|
1697
|
-
* // number
|
|
1698
|
-
* type T = FinalReturn<() => (foo: string) => (bar: string) => () => number>;
|
|
1699
|
-
* ```
|
|
1619
|
+
* Detects whether the passed in `v` is of type "object" where an object
|
|
1620
|
+
* is defined to be a string keyed dictionary style object. This means that
|
|
1621
|
+
* arrays are excluded, as well as functions which also have properties hanging
|
|
1622
|
+
* off of them.
|
|
1700
1623
|
*/
|
|
1701
|
-
|
|
1624
|
+
declare function isObject<T extends Narrowable>(i: T): IsObject<T>;
|
|
1625
|
+
declare function ifObject<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifObj: IF, notObj: ELSE): IfObject<T, IF, ELSE>;
|
|
1702
1626
|
|
|
1703
1627
|
/**
|
|
1704
|
-
*
|
|
1628
|
+
* **IsString**
|
|
1629
|
+
*
|
|
1630
|
+
* Type utility which returns true/false based on whether `T` is a
|
|
1631
|
+
* string (wide or narrow).
|
|
1705
1632
|
*/
|
|
1706
|
-
type
|
|
1707
|
-
|
|
1708
|
-
type DictFromKv<T extends readonly {
|
|
1709
|
-
key: string;
|
|
1710
|
-
value: unknown;
|
|
1711
|
-
}[]> = {
|
|
1712
|
-
[R in T[number] as R["key"]]: R["value"];
|
|
1713
|
-
};
|
|
1714
|
-
|
|
1633
|
+
type IsString<T> = T extends string ? true : false;
|
|
1715
1634
|
/**
|
|
1716
|
-
*
|
|
1635
|
+
* **IfString**
|
|
1717
1636
|
*
|
|
1718
|
-
*
|
|
1719
|
-
*
|
|
1720
|
-
* // ["foo", 1 ]
|
|
1721
|
-
* type Foo = KeyValue<Obj, "foo">;
|
|
1722
|
-
* ```
|
|
1723
|
-
*/
|
|
1724
|
-
type KeyValue<T extends object, K extends keyof T> = [K & keyof T, ExpandRecursively<T[K]>];
|
|
1725
|
-
|
|
1726
|
-
/**
|
|
1727
|
-
* Type utility which takes an object type and converts to an array of KV objects:
|
|
1728
|
-
* ```ts
|
|
1729
|
-
* // [ {key: "id", value: 123 } | {key: "foo", value: "bar" } ][]
|
|
1730
|
-
* type Arr = KvFrom<{ id: 123, foo: "bar" }>;
|
|
1731
|
-
* ```
|
|
1637
|
+
* Type utility which determines if `T` is a _string_ (wide or narrow) and
|
|
1638
|
+
* returns `IF` type if it is, otherwise returns the type `ELSE`.
|
|
1732
1639
|
*/
|
|
1733
|
-
type
|
|
1734
|
-
|
|
1735
|
-
key: K;
|
|
1736
|
-
value: T[K];
|
|
1737
|
-
};
|
|
1738
|
-
}[keyof T]>;
|
|
1640
|
+
type IfString<T extends Narrowable, //
|
|
1641
|
+
IF extends Narrowable, ELSE extends Narrowable> = IsString<T> extends true ? IF : IsString<T> extends false ? ELSE : IF | ELSE;
|
|
1739
1642
|
|
|
1740
1643
|
/**
|
|
1741
|
-
* **
|
|
1644
|
+
* **isString**
|
|
1742
1645
|
*
|
|
1743
|
-
*
|
|
1646
|
+
* Returns true or false on whether the passed in parameter is a
|
|
1647
|
+
* string (either a wide string or a string literal).
|
|
1744
1648
|
*
|
|
1745
|
-
*
|
|
1746
|
-
*
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1649
|
+
* The boolean return is traceable by the type system as well as the
|
|
1650
|
+
* runtime system.
|
|
1651
|
+
*/
|
|
1652
|
+
declare function isString<T>(i: T): IsString<T>;
|
|
1653
|
+
/**
|
|
1654
|
+
* **ifString**
|
|
1750
1655
|
*
|
|
1751
|
-
*
|
|
1656
|
+
* Strongly type-aware conditional statement which checks whether a value is
|
|
1657
|
+
* a _string_ and returns one of two values (strongly typed) based on the evaluation
|
|
1658
|
+
* of this criteria.
|
|
1659
|
+
*
|
|
1660
|
+
* @param val the value being tested for being a string
|
|
1661
|
+
* @param ifVal the value (strongly typed) returned if val is _string_
|
|
1662
|
+
* @param elseVal the value (strongly typed) returned if val is NOT a _string
|
|
1752
1663
|
*/
|
|
1753
|
-
|
|
1664
|
+
declare function ifString<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifVal: <E extends string>(t: E & T) => IF, elseVal: ELSE): IfString<T, IF, ELSE>;
|
|
1665
|
+
|
|
1666
|
+
declare function isSymbol<T>(i: T): T extends symbol ? true : false;
|
|
1754
1667
|
|
|
1755
|
-
type DictArrayFilterCallback<K extends keyof T, T extends object, R extends true | false> = (key: K, value: Pick<T, K>) => R;
|
|
1756
1668
|
/**
|
|
1757
|
-
*
|
|
1669
|
+
* Run-time and type checking of whether a variable is `true`.
|
|
1758
1670
|
*/
|
|
1759
|
-
|
|
1760
|
-
type DictKvTuple<K extends string> = [K, Record<K, unknown>];
|
|
1671
|
+
declare function isTrue<T extends Narrowable>(i: T): IsTrue<T>;
|
|
1761
1672
|
/**
|
|
1762
|
-
*
|
|
1763
|
-
*
|
|
1764
|
-
*
|
|
1765
|
-
*
|
|
1766
|
-
*
|
|
1767
|
-
*
|
|
1768
|
-
*
|
|
1769
|
-
*
|
|
1673
|
+
* **ifTrue**
|
|
1674
|
+
*
|
|
1675
|
+
* Strongly type-aware conditional statement which checks whether a value is
|
|
1676
|
+
* _true_.
|
|
1677
|
+
*
|
|
1678
|
+
* @param val the value being tested
|
|
1679
|
+
* @param ifVal the value (strongly typed) returned if val is _true_ value
|
|
1680
|
+
* @param elseVal the value (strongly typed) returned if val is NOT a _true_ value
|
|
1681
|
+
*
|
|
1682
|
+
* Note: at runtime there's no way to distinguish if the value was widely or loosely
|
|
1683
|
+
* typed so unlike the type utility there is no "MAYBE" state but if a wide type if
|
|
1684
|
+
* encountered the _type_ will the union of `IF` and `ELSE`.
|
|
1770
1685
|
*/
|
|
1771
|
-
|
|
1772
|
-
[K in keyof T]: DictArrayKv<K, T>;
|
|
1773
|
-
}[keyof T]>;
|
|
1686
|
+
declare function ifTrue<T extends boolean, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifVal: IF, elseVal: ELSE): IfTrue<T, IF, ELSE, IF | ELSE>;
|
|
1774
1687
|
|
|
1688
|
+
declare function isUndefined<T extends Narrowable>(i: T): undefined extends T ? true : false;
|
|
1775
1689
|
/**
|
|
1776
|
-
*
|
|
1690
|
+
* **ifUndefined**
|
|
1777
1691
|
*
|
|
1778
|
-
*
|
|
1779
|
-
*
|
|
1692
|
+
* Strongly type-aware conditional statement which checks whether a value is
|
|
1693
|
+
* _undefined_ and returns one of two values (strongly typed) based on the evaluation
|
|
1694
|
+
* of this criteria.
|
|
1695
|
+
*
|
|
1696
|
+
* @param val the value being tested
|
|
1697
|
+
* @param ifVal the value (strongly typed) returned if val is `undefined`
|
|
1698
|
+
* @param elseVal the value (strongly typed) returned if val is NOT `undefined`
|
|
1780
1699
|
*/
|
|
1781
|
-
|
|
1700
|
+
declare function ifUndefined<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifVal: IF, elseVal: ELSE): IsUndefined<T> extends true ? IF : ELSE;
|
|
1701
|
+
declare function ifDefined<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifVal: <V extends Exclude<T, undefined>>(v: V) => IF, elseVal: ELSE): IsUndefined<T> extends true ? IF : ELSE;
|
|
1782
1702
|
|
|
1703
|
+
interface Box<T> {
|
|
1704
|
+
__kind: "box";
|
|
1705
|
+
value: T;
|
|
1706
|
+
/**
|
|
1707
|
+
* Unbox the boxed value in the narrowest possible type.
|
|
1708
|
+
*
|
|
1709
|
+
* **note:** if the boxed value is a function with parameters you
|
|
1710
|
+
* can pass the parameters directly into the `b.unbox(params)` call.
|
|
1711
|
+
*/
|
|
1712
|
+
unbox: HasParameters<Box<T>["value"]> extends true ? Box<T>["value"] extends AnyFunction ? Box<T>["value"] extends (...args: infer A) => infer R ? <N extends A>(...args: N) => R : () => ReturnType<T> : () => T : () => T;
|
|
1713
|
+
}
|
|
1714
|
+
type BoxValue<T extends Box<any>> = T extends Box<infer V> ? V : never;
|
|
1715
|
+
type BoxedFnParams<T extends Box<any>> = T extends Box<infer V> ? V extends (...args: infer A) => any ? A : [] : [];
|
|
1716
|
+
type BoxedReturn<T extends Box<any>> = T extends Box<infer V> ? V extends Function ? ReturnType<T["value"]> : T["value"] : never;
|
|
1717
|
+
type NarrowBox<T> = <N extends BoxedFnParams<Box<T>> | First<BoxedFnParams<Box<T>>>>() => N extends BoxedFnParams<Box<T>> ? T extends (...args: any[]) => any ? (...args: N) => Box<T>["unbox"] : never : (first: N, ...rest: AfterFirst<BoxedFnParams<Box<T>>>) => BoxedReturn<Box<T>>;
|
|
1783
1718
|
/**
|
|
1784
|
-
*
|
|
1785
|
-
*
|
|
1786
|
-
*
|
|
1787
|
-
*
|
|
1719
|
+
* Allows a value with an inner-type to be boxed into a dictionary
|
|
1720
|
+
* so that this type inference is preserved with the help of
|
|
1721
|
+
* [instantiation expressions](https://devblogs.microsoft.com/typescript/announcing-typescript-4-7-beta/#instantiation-expressions).
|
|
1722
|
+
*
|
|
1723
|
+
* NOTE: this feature is immature at best right now
|
|
1788
1724
|
*/
|
|
1789
|
-
|
|
1790
|
-
|
|
1725
|
+
declare function box<T extends Narrowable>(value: T): Box<T>;
|
|
1726
|
+
declare function isBox(thing: Narrowable): thing is Box<any>;
|
|
1791
1727
|
/**
|
|
1792
|
-
*
|
|
1793
|
-
* array.
|
|
1728
|
+
* **boxDictionaryValues**(dict)
|
|
1794
1729
|
*
|
|
1795
|
-
*
|
|
1796
|
-
* const test = [ ["foo", 1], ["bar", 2] ];
|
|
1797
|
-
* // "foo" | "bar"
|
|
1798
|
-
* type F = FirstOfEach<typeof test>;
|
|
1799
|
-
* ```
|
|
1730
|
+
* Runtime utility which boxes each value in a dictionary
|
|
1800
1731
|
*/
|
|
1801
|
-
|
|
1802
|
-
|
|
1732
|
+
declare function boxDictionaryValues<T extends {}>(dict: T): { [K in keyof T]: Box<T[K]>; };
|
|
1733
|
+
type Unbox<T> = T extends Box<infer U> ? U : T;
|
|
1803
1734
|
/**
|
|
1804
|
-
*
|
|
1805
|
-
*
|
|
1806
|
-
*
|
|
1807
|
-
* // { foo: 1; bar: "hi" }
|
|
1808
|
-
* type Dict = FromDictArray<[["foo", { foo: 1 }], ["bar", { bar: "hi" }]]>;
|
|
1809
|
-
* ```
|
|
1735
|
+
* **unbox**(maybeBox)
|
|
1736
|
+
*
|
|
1737
|
+
* Unboxes a value if it was a box; otherwise it leaves _as is_.
|
|
1810
1738
|
*/
|
|
1811
|
-
|
|
1739
|
+
declare function unbox<T>(val: T): Unbox<T>;
|
|
1812
1740
|
|
|
1813
1741
|
/**
|
|
1814
|
-
*
|
|
1815
|
-
* array.
|
|
1742
|
+
* Build a _type_ from two run-time dictionaries.
|
|
1816
1743
|
*
|
|
1817
|
-
*
|
|
1818
|
-
*
|
|
1819
|
-
* type F = SecondOfEach<[ ["foo", 1], ["bar", 2] ]>;
|
|
1820
|
-
* ```
|
|
1744
|
+
* 1. The _first_ -- which is optional -- is interpreted as a _literal_ type definition
|
|
1745
|
+
* 2. The _second_ dictionary is interpreted as a "wide" definition of prop types
|
|
1821
1746
|
*/
|
|
1822
|
-
|
|
1747
|
+
declare function defineType<N extends Narrowable, TLiteral extends Record<string, N>>(literal?: TLiteral): <TWide extends object>(wide?: TWide) => ExpandRecursively<TWide & TLiteral>;
|
|
1823
1748
|
|
|
1824
|
-
declare function createFnWithProps<F extends Function, P extends {}>(fn: F, props: P): F & P;
|
|
1825
1749
|
/**
|
|
1826
|
-
*
|
|
1750
|
+
* An identity function for any type, with the goal of preserving literal type information
|
|
1751
|
+
* whereever possible.
|
|
1827
1752
|
*/
|
|
1828
|
-
declare
|
|
1753
|
+
declare const identity: <N extends Narrowable, T extends string | number | boolean | symbol | Record<any, N> | null | undefined>(v: T) => T;
|
|
1754
|
+
|
|
1829
1755
|
/**
|
|
1830
|
-
*
|
|
1756
|
+
* Takes an object as input --which has an `id` property and returns it as the same
|
|
1757
|
+
* run-time content but with the _type_ of the `id` property being forced to a literal type
|
|
1831
1758
|
*/
|
|
1832
|
-
declare function
|
|
1759
|
+
declare function idLiteral<T extends {
|
|
1760
|
+
id: I;
|
|
1761
|
+
}, I extends PropertyKey>(o: T): T & {
|
|
1762
|
+
id: T["id"];
|
|
1763
|
+
};
|
|
1764
|
+
/**
|
|
1765
|
+
* Takes an object as input --which has an `name` property and returns it as the same
|
|
1766
|
+
* run-time content but with the _type_ of the `name` property being forced to a literal type
|
|
1767
|
+
*/
|
|
1768
|
+
declare function nameLiteral<T extends {
|
|
1769
|
+
name: I;
|
|
1770
|
+
}, I extends PropertyKey>(o: T): T & {
|
|
1771
|
+
name: T["name"];
|
|
1772
|
+
};
|
|
1773
|
+
/**
|
|
1774
|
+
* Takes an object as input --which has an `kind` property and returns it as the same
|
|
1775
|
+
* run-time content but with the _type_ of the `kind` property being forced to a literal type
|
|
1776
|
+
*/
|
|
1777
|
+
declare function kindLiteral<T extends {
|
|
1778
|
+
kind: I;
|
|
1779
|
+
}, I extends PropertyKey>(o: T): T & {
|
|
1780
|
+
kind: T["kind"];
|
|
1781
|
+
};
|
|
1782
|
+
declare function idTypeGuard<T extends {
|
|
1783
|
+
id: I;
|
|
1784
|
+
}, I extends PropertyKey>(_o: T): _o is T & {
|
|
1785
|
+
id: I;
|
|
1786
|
+
};
|
|
1787
|
+
/**
|
|
1788
|
+
* Takes an object as input and infers the narrow literal types of the property
|
|
1789
|
+
* values on the object.
|
|
1790
|
+
*
|
|
1791
|
+
* > Note: this addresses this [a known TS gap](https://github.com/microsoft/TypeScript/issues/30680).
|
|
1792
|
+
* > Hopefully at some point this will be addressed in the language.
|
|
1793
|
+
*/
|
|
1794
|
+
declare function literal<N extends Narrowable, T extends Record<keyof T, N>>(obj: T): T;
|
|
1833
1795
|
|
|
1834
1796
|
/**
|
|
1835
|
-
*
|
|
1797
|
+
* **StripEnding**`<T, U>`
|
|
1798
|
+
*
|
|
1799
|
+
* Will strip off of `T` the ending defined by `U` when
|
|
1800
|
+
* both are string literals.
|
|
1801
|
+
* ```ts
|
|
1802
|
+
* type T = "Hello World";
|
|
1803
|
+
* type U = " World";
|
|
1804
|
+
* // "Hello"
|
|
1805
|
+
* type R = StripEnding<T,U>;
|
|
1806
|
+
* ```
|
|
1836
1807
|
*/
|
|
1837
|
-
|
|
1808
|
+
type StripTrailing<T extends string, U extends string> = IfLiteral<T, string extends U ? never : T extends `${infer Before}${U}` ? Before : T, string>;
|
|
1838
1809
|
|
|
1839
1810
|
/**
|
|
1840
|
-
* **
|
|
1811
|
+
* **stripTrailing**(content, strip)
|
|
1841
1812
|
*
|
|
1842
|
-
*
|
|
1813
|
+
* Runtime utility which ensures that last part of a string has substring
|
|
1814
|
+
* removed if it exists and that strong typing is preserved.
|
|
1815
|
+
*/
|
|
1816
|
+
declare function stripTrailing<T extends string, U extends string>(content: T, strip: U): StripTrailing<T, U>;
|
|
1817
|
+
|
|
1818
|
+
/**
|
|
1819
|
+
* **EnsureTrailing**`<T, U>`
|
|
1843
1820
|
*
|
|
1844
|
-
*
|
|
1845
|
-
*
|
|
1821
|
+
* Will ensure that `T` ends with the substring `U` when
|
|
1822
|
+
* both are string literals.
|
|
1846
1823
|
*
|
|
1847
1824
|
* ```ts
|
|
1848
|
-
*
|
|
1849
|
-
*
|
|
1850
|
-
*
|
|
1851
|
-
*
|
|
1852
|
-
* );
|
|
1825
|
+
* type T = "Hello";
|
|
1826
|
+
* type U = " World";
|
|
1827
|
+
* // "Hello World"
|
|
1828
|
+
* type R = EnsureTrailing<T,U>;
|
|
1853
1829
|
* ```
|
|
1854
1830
|
*/
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
declare const api: <N extends Narrowable, TPrivate extends Readonly<Record<any, N>>>(priv: TPrivate) => <TPublic extends object>(pub: TPublic) => () => TPublic;
|
|
1831
|
+
type EnsureTrailing<T extends string, U extends string> = IfLiteral<T, string extends U ? never : T extends `${string}${U}` ? T : `${T}${U}`, string>;
|
|
1858
1832
|
|
|
1859
1833
|
/**
|
|
1860
|
-
*
|
|
1861
|
-
* the logical **AND** operator.
|
|
1834
|
+
* **ensureTrailing**(content, strip)
|
|
1862
1835
|
*
|
|
1863
|
-
*
|
|
1836
|
+
* Runtime utility which ensures that last part of a string -- `content` -- has the
|
|
1837
|
+
* substring `ensure` at the end and adds it if not present.
|
|
1864
1838
|
*/
|
|
1865
|
-
declare
|
|
1839
|
+
declare function ensureTrailing<T extends string, U extends string>(content: T, ensure: U): EnsureTrailing<T, U>;
|
|
1866
1840
|
|
|
1867
|
-
|
|
1841
|
+
/**
|
|
1842
|
+
* Indicates whether `T` has _all_ uppercase characters in it.
|
|
1843
|
+
* ```ts
|
|
1844
|
+
* // true
|
|
1845
|
+
* type T = AllCaps<"FOOBAR">;
|
|
1846
|
+
* // false
|
|
1847
|
+
* type T = AllCaps<"FooBar">;
|
|
1848
|
+
* // "unknown"
|
|
1849
|
+
* type T = AllCaps<string>;
|
|
1850
|
+
* ```
|
|
1851
|
+
*/
|
|
1852
|
+
type AllCaps<T extends string> = string extends T ? "unknown" : T extends Uppercase<T> ? true : false;
|
|
1868
1853
|
|
|
1869
1854
|
/**
|
|
1870
|
-
*
|
|
1871
|
-
* the logical **NOT** operator.
|
|
1855
|
+
* **Break<T,D>**
|
|
1872
1856
|
*
|
|
1873
|
-
*
|
|
1857
|
+
* Takes a string `T`, and splits it into a tuple of the form `[F, R]`.
|
|
1858
|
+
* ```ts
|
|
1859
|
+
* // ["the", " long and winding road"]
|
|
1860
|
+
* type T1 = Break<"the long and winding road", " ">;
|
|
1861
|
+
* // ["there", " I was, there I was"]
|
|
1862
|
+
* type T2 = Break<"there I was, there I was", " ">;
|
|
1863
|
+
* ```
|
|
1874
1864
|
*/
|
|
1875
|
-
|
|
1865
|
+
type Break<T extends string, D extends string> = (string extends T ? [string, string] : (T extends `${infer F}${D}${infer _R}` ? (F extends `${infer _X}${D}${infer _Y}` ? never : (T extends `${F}${infer R}` ? [F, R] : never)) : [T, ""]));
|
|
1876
1866
|
|
|
1877
|
-
type FilterStarts = {
|
|
1878
|
-
/** one or more string which the value is allowed to start with */
|
|
1879
|
-
startsWith: string | string[];
|
|
1880
|
-
};
|
|
1881
|
-
type FilterIs = {
|
|
1882
|
-
/** whether a string _**is**_ of a particular value */
|
|
1883
|
-
is: string | string[];
|
|
1884
|
-
};
|
|
1885
|
-
type FilterEnds = {
|
|
1886
|
-
endsWith: string | string[];
|
|
1887
|
-
};
|
|
1888
|
-
type FilterContains = {
|
|
1889
|
-
/** whether any of the strings specified are _contained_ in the value */
|
|
1890
|
-
contains: string | string[];
|
|
1891
|
-
};
|
|
1892
|
-
type FilterEquals = {
|
|
1893
|
-
/** one or more values which _equal_ the value passed in */
|
|
1894
|
-
equals: number | number[];
|
|
1895
|
-
};
|
|
1896
|
-
type FilterNotEqual = {
|
|
1897
|
-
/** one or more values which ALL _do not equal_ the value passed in */
|
|
1898
|
-
notEqual: number | number[];
|
|
1899
|
-
};
|
|
1900
|
-
type FilterGreaterThan = {
|
|
1901
|
-
/** the incoming value is greater than this value */
|
|
1902
|
-
greaterThan: number;
|
|
1903
|
-
};
|
|
1904
|
-
type FilterLessThan = {
|
|
1905
|
-
/** the incoming value is less than this value */
|
|
1906
|
-
lessThan: number;
|
|
1907
|
-
};
|
|
1908
|
-
type StringFilter = FilterIs | FilterStarts | FilterEnds | FilterContains | (FilterStarts & FilterEnds) | (FilterStarts & FilterContains) | (FilterEnds & FilterContains) | (FilterStarts & FilterEnds & FilterContains);
|
|
1909
|
-
type NumericFilter = FilterEquals | FilterNotEqual | FilterGreaterThan | FilterLessThan | (FilterEquals & FilterNotEqual) | (FilterEquals & FilterGreaterThan) | (FilterEquals & FilterLessThan) | (FilterNotEqual & FilterGreaterThan) | (FilterNotEqual & FilterLessThan) | (FilterGreaterThan & FilterLessThan) | (FilterEquals & FilterGreaterThan & FilterLessThan) | (FilterNotEqual & FilterGreaterThan & FilterLessThan) | (FilterEquals & FilterNotEqual & FilterGreaterThan & FilterLessThan);
|
|
1910
|
-
type FilterDefn = StringFilter | NumericFilter;
|
|
1911
|
-
type NotFilter = {
|
|
1912
|
-
/**
|
|
1913
|
-
* **not**
|
|
1914
|
-
*
|
|
1915
|
-
* If you want to build a filter who's conditions being met results in _filtering_
|
|
1916
|
-
* the value rather than accepting it then choose this.
|
|
1917
|
-
*/
|
|
1918
|
-
not: FilterDefn;
|
|
1919
|
-
};
|
|
1920
|
-
declare function isNotFilter(f: FilterDefn | NotFilter): f is NotFilter;
|
|
1921
|
-
type UnwrapNot<T extends FilterDefn | NotFilter> = T extends NotFilter ? T["not"] extends StringFilter ? StringFilter : NumericFilter : T;
|
|
1922
|
-
declare function isNumericFilter(filter: FilterDefn): filter is NumericFilter;
|
|
1923
|
-
type UndefinedValue<U extends boolean> = true extends U ? "undefined treated as 'true'" : U extends "no-impact" ? "undefined treated in no-impact fashion" : "undefined treated as 'false'";
|
|
1924
|
-
type UndefinedTreatment = "undefined treated as 'true'" | "undefined treated as 'false'";
|
|
1925
|
-
type LogicalCombinator = "AND" | "OR";
|
|
1926
1867
|
/**
|
|
1927
|
-
*
|
|
1928
|
-
*
|
|
1929
|
-
* A filter function derived from the `filter()` configurator. This function is intended to provide a type-strong _filter_ function which can be used like so:
|
|
1930
|
-
* be used like:
|
|
1868
|
+
* Concatenates two arrays (of literals).
|
|
1931
1869
|
* ```ts
|
|
1932
|
-
*
|
|
1933
|
-
*
|
|
1870
|
+
* // [ "foo", "bar", "baz" ]
|
|
1871
|
+
* type T = ArrConcat<["foo"], ["bar", "baz"]>;
|
|
1934
1872
|
* ```
|
|
1935
|
-
*
|
|
1936
|
-
*/
|
|
1937
|
-
type FilterFn<T extends StringFilter | NumericFilter> = T extends StringFilter ? <V extends string | undefined>(input: V) => boolean : <V extends number | undefined>(input: V) => boolean;
|
|
1938
|
-
/**
|
|
1939
|
-
* Defines a logical function for each condition type
|
|
1940
1873
|
*/
|
|
1941
|
-
type
|
|
1874
|
+
type ArrConcat<A extends any[], B extends any[]> = [...A, ...B];
|
|
1875
|
+
|
|
1942
1876
|
/**
|
|
1943
|
-
*
|
|
1944
|
-
*
|
|
1945
|
-
* A higher order helper utility which builds a boolean _filter_ function based on a simple
|
|
1946
|
-
* configuration object. Support either _string_ or _numeric_ filters.
|
|
1947
|
-
*
|
|
1877
|
+
* Type utility which takes a string `S` and replaces the substring `W` with `P`.
|
|
1948
1878
|
* ```ts
|
|
1949
|
-
* const
|
|
1950
|
-
*
|
|
1879
|
+
* const fooy = "fooy";
|
|
1880
|
+
* // "Foo"
|
|
1881
|
+
* type Foo = Replace<typeof fooy, "y", "">;
|
|
1951
1882
|
* ```
|
|
1952
1883
|
*
|
|
1953
|
-
*
|
|
1954
|
-
* is defined as having -- if there is more than one -- will be logically combined using AND
|
|
1955
|
-
* unless specified otherwise in the third parameter.
|
|
1956
|
-
*
|
|
1957
|
-
* How a value of _undefined_ will be treated is stated in the second parameter but defaults
|
|
1958
|
-
* to "no-impact" which means it's `false` when the logicCombinator is OR but defaults
|
|
1959
|
-
* to `true` when the logicCombinator is AND.
|
|
1884
|
+
* Note: _the first match is replaced and all subsequent matches are ignored_
|
|
1960
1885
|
*/
|
|
1961
|
-
|
|
1886
|
+
type Replace<S extends string, W extends string, P extends string> = S extends "" ? "" : W extends "" ? S : S extends `${infer F}${W}${infer E}` ? `${F}${P}${E}` : S;
|
|
1962
1887
|
|
|
1963
1888
|
/**
|
|
1964
|
-
*
|
|
1965
|
-
* all the keys being the strings and values set to `true`.
|
|
1889
|
+
* Trims off whitespace on left of string
|
|
1966
1890
|
* ```ts
|
|
1967
|
-
* //
|
|
1968
|
-
*
|
|
1969
|
-
*
|
|
1970
|
-
*
|
|
1891
|
+
* // "foobar "
|
|
1892
|
+
* type T = TrimLeft<"\n\t foobar ">;
|
|
1893
|
+
* // string
|
|
1894
|
+
* type T = TrimLeft<string>;
|
|
1971
1895
|
* ```
|
|
1972
1896
|
*/
|
|
1973
|
-
|
|
1897
|
+
type TrimLeft<S extends string> = string extends S ? string : S extends `${Whitespace}${infer Right}` ? TrimLeft<Right> : S;
|
|
1974
1898
|
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
*/
|
|
1984
|
-
rw<K extends keyof T>(prop: K): Omit<T, K> & Record<K, Readonly<T[K]>>;
|
|
1985
|
-
}
|
|
1986
|
-
declare function defineProperties<T extends {}>(obj: T): DefinePropertiesApi<T>;
|
|
1899
|
+
/**
|
|
1900
|
+
* Provides the _left_ whitespace of a string
|
|
1901
|
+
* ```ts
|
|
1902
|
+
* // "\n\t "
|
|
1903
|
+
* type T = LeftWhitespace<"\n\t foobar">;
|
|
1904
|
+
* ```
|
|
1905
|
+
*/
|
|
1906
|
+
type LeftWhitespace<S extends string> = string extends S ? string : Replace<S, TrimLeft<S>, "">;
|
|
1987
1907
|
|
|
1988
1908
|
/**
|
|
1989
|
-
*
|
|
1990
|
-
*
|
|
1991
|
-
*
|
|
1992
|
-
*
|
|
1993
|
-
*
|
|
1909
|
+
* Trims off whitespace on left of string
|
|
1910
|
+
* ```ts
|
|
1911
|
+
* // "\n foobar"
|
|
1912
|
+
* type T = TrimRight<"\n foobar \t">;
|
|
1913
|
+
* // string
|
|
1914
|
+
* type T = TrimRight<string>;
|
|
1915
|
+
* ```
|
|
1994
1916
|
*/
|
|
1995
|
-
|
|
1917
|
+
type TrimRight<S extends string> = string extends S ? string : S extends `${infer Right}${Whitespace}` ? TrimRight<Right> : S;
|
|
1996
1918
|
|
|
1997
|
-
interface Uniqueness<T> {
|
|
1998
|
-
/** boolean flag to indicate whether the property was unique across all records */
|
|
1999
|
-
isUnique: boolean;
|
|
2000
|
-
/** the overall number of records which contained the property */
|
|
2001
|
-
size: number;
|
|
2002
|
-
/** specifies if undefined values were encountered for this property */
|
|
2003
|
-
includedUndefined: boolean;
|
|
2004
|
-
/** the unique values for the property across all records */
|
|
2005
|
-
values: readonly T[];
|
|
2006
|
-
}
|
|
2007
|
-
type DictArrApi<T extends Record<string, Narrowable>, A extends readonly T[]> = {
|
|
2008
|
-
length: number;
|
|
2009
|
-
toLookup<PL extends RequiredKeys<T, string> & keyof T & string>(prop: PL): UniqueForProp<A, PL> extends string ? Record<UniqueForProp<A, PL>, T> : Record<string, T>;
|
|
2010
|
-
sum<PS extends RequiredKeys<T, number> | OptionalKeys<T, number>>(prop: PS): number;
|
|
2011
|
-
count<PC extends OptionalKeys<T>>(prop: PC): number;
|
|
2012
|
-
unique<PU extends Keys<T> & keyof T>(prop: PU): Uniqueness<T[PU]>;
|
|
2013
|
-
};
|
|
2014
1919
|
/**
|
|
2015
|
-
*
|
|
2016
|
-
*
|
|
1920
|
+
* Provides the _left_ whitespace of a string
|
|
1921
|
+
* ```ts
|
|
1922
|
+
* // "\n\t "
|
|
1923
|
+
* type T = LeftWhitespace<"\n\t foobar">;
|
|
1924
|
+
* ```
|
|
2017
1925
|
*/
|
|
2018
|
-
|
|
1926
|
+
type RightWhitespace<S extends string> = string extends S ? string : Replace<S, TrimRight<S>, "">;
|
|
2019
1927
|
|
|
2020
1928
|
/**
|
|
2021
|
-
*
|
|
2022
|
-
*
|
|
2023
|
-
* Provides an _iterable_ over the passed in dictionary object where each iteration
|
|
2024
|
-
* provides a tuple of `[ key, value ]` which preserve type literals.
|
|
1929
|
+
* Type utility that provides the _length_ of a given string type in a way which
|
|
1930
|
+
* is _not_ limited to TS's recursive string length of roughly 48.
|
|
2025
1931
|
*
|
|
2026
|
-
* For example:
|
|
2027
1932
|
* ```ts
|
|
2028
|
-
*
|
|
2029
|
-
*
|
|
2030
|
-
* for (const [k, v] of entries(obj)) { ... }
|
|
1933
|
+
* // 3
|
|
1934
|
+
* type Three = StringLength<"foo">;
|
|
2031
1935
|
* ```
|
|
2032
1936
|
*/
|
|
2033
|
-
|
|
2034
|
-
[Symbol.iterator](): Generator<I, void, unknown>;
|
|
2035
|
-
};
|
|
1937
|
+
type StringLength<S extends string, R extends number[] = []> = S extends `${infer _First}${infer _Second}${infer _Third}${infer _Fourth}${infer _Fifth}${infer _Sixth}${infer _Sevebnth}${infer _Eighth}${infer _Ninth}${infer _Tenth}${infer Rest}` ? StringLength<Rest, [...R, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]> : S extends `${infer _First}${infer _Second}${infer _Third}${infer _Fourth}${infer _Fifth}${infer _Sixth}${infer _Sevebnth}${infer _Eighth}${infer _Ninth}${infer Rest}` ? StringLength<Rest, [...R, 1, 1, 1, 1, 1, 1, 1, 1, 1]> : S extends `${infer _First}${infer _Second}${infer _Third}${infer _Fourth}${infer _Fifth}${infer _Sixth}${infer _Sevebnth}${infer _Eighth}${infer Rest}` ? StringLength<Rest, [...R, 1, 1, 1, 1, 1, 1, 1, 1]> : S extends `${infer _First}${infer _Second}${infer _Third}${infer _Fourth}${infer _Fifth}${infer _Sixth}${infer _Sevebnth}${infer Rest}` ? StringLength<Rest, [...R, 1, 1, 1, 1, 1, 1, 1]> : S extends `${infer _First}${infer _Second}${infer _Third}${infer _Fourth}${infer _Fifth}${infer _Sixth}${infer Rest}` ? StringLength<Rest, [...R, 1, 1, 1, 1, 1, 1]> : S extends `${infer _First}${infer _Second}${infer _Third}${infer _Fourth}${infer _Fifth}}${infer Rest}` ? StringLength<Rest, [...R, 1, 1, 1, 1, 1]> : S extends `${infer _First}${infer _Second}${infer _Third}${infer _Fourth}${infer Rest}` ? StringLength<Rest, [...R, 1, 1, 1, 1]> : S extends `${infer _First}${infer _Second}${infer _Third}${infer Rest}` ? StringLength<Rest, [...R, 1, 1, 1]> : S extends `${infer _First}${infer _Second}${infer Rest}` ? StringLength<Rest, [...R, 1, 1]> : S extends `${infer _First}${infer Rest}` ? StringLength<Rest, [...R, 1]> : [...R]["length"];
|
|
2036
1938
|
|
|
2037
1939
|
/**
|
|
2038
|
-
*
|
|
2039
|
-
*
|
|
2040
|
-
* Maps over a dictionary, preserving the keys but allowing the values to be mutated.
|
|
2041
|
-
*
|
|
1940
|
+
* Trims off blank spaces, `\n` and `\t` characters from both sides of a _string literal_.
|
|
2042
1941
|
* ```ts
|
|
2043
|
-
*
|
|
2044
|
-
*
|
|
2045
|
-
*
|
|
1942
|
+
* // "foobar"
|
|
1943
|
+
* type T = Trim<"\n\t foobar ">;
|
|
1944
|
+
* // string
|
|
1945
|
+
* type T = Trim<string>;
|
|
2046
1946
|
* ```
|
|
2047
1947
|
*/
|
|
2048
|
-
|
|
1948
|
+
type Trim<S extends string> = string extends S ? string : S extends `${Whitespace}${infer Right}` ? Trim<Right> : S extends `${infer Left}${Whitespace}` ? Trim<Left> : S;
|
|
2049
1949
|
|
|
2050
1950
|
/**
|
|
2051
|
-
*
|
|
2052
|
-
* dictionary of the type `{ a: true, b: true, c: true }`
|
|
1951
|
+
* An email address
|
|
2053
1952
|
*/
|
|
2054
|
-
|
|
1953
|
+
type Email = `${string}@${string}.${string}`;
|
|
1954
|
+
type Zip5 = `${NumericString}${NumericString}${string}${NumericString}`;
|
|
1955
|
+
type Zip4 = `${NumericString}${string}`;
|
|
1956
|
+
/**
|
|
1957
|
+
* A relatively strong type for Zip5 or Zip5+4 zip codes
|
|
1958
|
+
*/
|
|
1959
|
+
type ZipCode = Zip5 | `${Zip5}-${Zip4}`;
|
|
2055
1960
|
|
|
2056
1961
|
/**
|
|
2057
|
-
*
|
|
1962
|
+
* If **ALL CAPS** it converts to all lowercase; if not then it does nothing */
|
|
1963
|
+
type LowerAllCaps<T extends string> = AllCaps<T> extends true ? Lowercase<T> : T;
|
|
1964
|
+
|
|
1965
|
+
type Delimiter = "_" | "-" | " ";
|
|
1966
|
+
/** convert all delimiters to dashes */
|
|
1967
|
+
type DashDelim<T extends string> = T extends `${infer Begin}${" "}${infer Rest}` ? DashDelim<`${Begin}-${Rest}`> : T extends `${infer Begin}${"_"}${infer Rest}` ? DashDelim<`${Begin}-${Rest}`> : T;
|
|
1968
|
+
/**
|
|
1969
|
+
* Converts a string literal type to a **PascalCase** representation.
|
|
2058
1970
|
* ```ts
|
|
2059
|
-
* //
|
|
2060
|
-
*
|
|
1971
|
+
* // "FooBar"
|
|
1972
|
+
* type T = PascalCase<"fooBar">;
|
|
1973
|
+
* type T = PascalCase<"foo-bar">;
|
|
1974
|
+
* type T = PascalCase<"foo_bar">;
|
|
1975
|
+
* type T = PascalCase<"\n foo_bar \t">;
|
|
2061
1976
|
* ```
|
|
2062
1977
|
*/
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
key: K;
|
|
2067
|
-
value: Mutable<T>[K];
|
|
2068
|
-
}; } : never)[keyof T], LastInUnion<(Mutable<T> extends infer T_1 extends object ? { [K in keyof T_1]: {
|
|
2069
|
-
key: K;
|
|
2070
|
-
value: Mutable<T>[K];
|
|
2071
|
-
}; } : never)[keyof T]>> : KvFrom<Mutable<T>>;
|
|
1978
|
+
type PascalCase<S extends string> = string extends S ? string : Trim<DashDelim<LowerAllCaps<S>>> extends `${infer Begin}${Delimiter}${infer Rest}` ? PascalCase<`${Capitalize<Begin>}${Capitalize<Rest>}`> : Capitalize<Trim<LowerAllCaps<S>>>;
|
|
1979
|
+
|
|
1980
|
+
type CamelCase<S extends string> = string extends S ? string : Uncapitalize<PascalCase<S>>;
|
|
2072
1981
|
|
|
2073
|
-
interface Array$1<T> {
|
|
2074
|
-
filter<U extends T>(pred: (a: T) => a is U): U[];
|
|
2075
|
-
}
|
|
2076
1982
|
/**
|
|
2077
|
-
*
|
|
2078
|
-
* value pair.
|
|
1983
|
+
* Capitalize all words in a string
|
|
2079
1984
|
*/
|
|
2080
|
-
|
|
1985
|
+
type CapitalizeWords<S extends string> = S extends `${infer L} ${infer R}` ? `${CapitalizeWords<L>} ${CapitalizeWords<R>}` : S extends `${infer L},${infer R}` ? `${CapitalizeWords<L>},${CapitalizeWords<R>}` : S extends `${infer L}.${infer R}` ? `${CapitalizeWords<L>}.${CapitalizeWords<R>}` : Capitalize<S>;
|
|
1986
|
+
|
|
1987
|
+
type DashToSnake<T extends string> = T extends `${infer HEAD}-${infer TAIL}` ? DashToSnake<`${HEAD}_${TAIL}`> : T;
|
|
2081
1988
|
|
|
2082
1989
|
/**
|
|
2083
|
-
*
|
|
2084
|
-
*
|
|
2085
|
-
*
|
|
2086
|
-
*
|
|
2087
|
-
*
|
|
2088
|
-
*
|
|
1990
|
+
* Indicates whether `T` has uppercase characters in it.
|
|
1991
|
+
* ```ts
|
|
1992
|
+
* // true
|
|
1993
|
+
* type T = HasUppercase<"Foobar">;
|
|
1994
|
+
* // false
|
|
1995
|
+
* type T = HasUppercase<"foobar">;
|
|
1996
|
+
* // "unknown"
|
|
1997
|
+
* type T = HasUppercase<string>;
|
|
1998
|
+
* ```
|
|
2089
1999
|
*/
|
|
2090
|
-
|
|
2000
|
+
type HasUppercase<T extends string> = string extends T ? "unknown" : T extends `${string}${UpperAlpha}${string}` ? true : false;
|
|
2091
2001
|
|
|
2002
|
+
type _DU<T extends string> = T extends Lowercase<T> ? T : `-${Lowercase<T>}`;
|
|
2092
2003
|
/**
|
|
2093
|
-
* Converts
|
|
2004
|
+
* Converts uppercase characters to a dash and then the lowercase equivalent
|
|
2094
2005
|
* ```ts
|
|
2095
|
-
* //
|
|
2096
|
-
*
|
|
2006
|
+
* // "one-two-three"
|
|
2007
|
+
* type T = DashUppercase<"oneTwoThree">;
|
|
2097
2008
|
* ```
|
|
2098
2009
|
*
|
|
2099
|
-
*
|
|
2010
|
+
* _Intended to be used as a lower level utility; prefer `Dasherize<T>` for more full-fledged
|
|
2011
|
+
* dash solution_.
|
|
2100
2012
|
*/
|
|
2101
|
-
|
|
2102
|
-
key: K;
|
|
2103
|
-
value: V;
|
|
2104
|
-
}>[]>(kvArr: T): DictFromKv<T>;
|
|
2013
|
+
type DashUppercase<T extends string> = HasUppercase<T> extends false ? T : T extends `${infer C0}${infer C1}${infer R}` ? `${_DU<C0>}${_DU<C1>}${DashUppercase<R>}` : T extends `${infer C0}${infer R}` ? `${_DU<C0>}${DashUppercase<R>}` : "";
|
|
2105
2014
|
|
|
2015
|
+
type OneToOne = `1:1`;
|
|
2016
|
+
type OneToMany = `1:M`;
|
|
2017
|
+
type OneToZero = `1:0`;
|
|
2018
|
+
type ZeroToOne = `0:1`;
|
|
2019
|
+
type ZeroToMany = `0:M`;
|
|
2020
|
+
type ZeroToZero = `0:0`;
|
|
2021
|
+
type ManyToMany = "M:M";
|
|
2022
|
+
type ManyToOne = "M:1";
|
|
2023
|
+
type ManyToZero = "M:0";
|
|
2024
|
+
type CardinalityNode = "0" | "1" | "M";
|
|
2106
2025
|
/**
|
|
2107
|
-
*
|
|
2026
|
+
* Cardinality which expects a singular input and requires
|
|
2027
|
+
* 1 or many outputs.
|
|
2028
|
+
*
|
|
2029
|
+
* Note: choose `CardinalityFilter1` if you want to allow output
|
|
2030
|
+
* to have no outputs.
|
|
2108
2031
|
*/
|
|
2109
|
-
type
|
|
2110
|
-
type AsArray<T, W extends boolean = false> = T extends any[] ? W extends true ? Widen<T> : T : W extends true ? UndefinedArrayIsUnknown<Widen<T>[]> : UndefinedArrayIsUnknown<T[]>;
|
|
2032
|
+
type Cardinality1 = OneToOne | OneToMany;
|
|
2111
2033
|
/**
|
|
2112
|
-
*
|
|
2113
|
-
*
|
|
2114
|
-
* - if it was already an array than this just serves as an _identity_ function
|
|
2115
|
-
* - if it was not then it wraps the element into a one element array of the
|
|
2116
|
-
* given type
|
|
2117
|
-
*
|
|
2118
|
-
* Note: by default the _type_ of values will be intentionally widened so that the value "abc"
|
|
2119
|
-
* is of type `string` not the literal `abc`. If you want to keep literal types then
|
|
2120
|
-
* change the optional _widen_ parameter to _false_.
|
|
2034
|
+
* Cardinality which expects a singular input and maps to 0,
|
|
2035
|
+
* 1, or many outputs.
|
|
2121
2036
|
*/
|
|
2122
|
-
|
|
2123
|
-
|
|
2037
|
+
type CardinalityFilter1 = OneToOne | OneToMany | OneToZero;
|
|
2124
2038
|
/**
|
|
2125
|
-
*
|
|
2126
|
-
*
|
|
2127
|
-
* ```ts
|
|
2128
|
-
* const data = [ {}, {}, {} ];
|
|
2129
|
-
*
|
|
2130
|
-
* ```
|
|
2131
|
-
*
|
|
2132
|
-
* @ignore not implemented
|
|
2039
|
+
* Cardinality which expects a singular input which is allowed to be
|
|
2040
|
+
* _undefined_ or the expected type.
|
|
2133
2041
|
*/
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
type ExplicitFunction<P extends any[], R extends any> = (...args: P) => R;
|
|
2042
|
+
type Cardinality0 = ZeroToOne | ZeroToMany | OneToOne | OneToMany;
|
|
2137
2043
|
/**
|
|
2138
|
-
*
|
|
2139
|
-
*
|
|
2044
|
+
* Cardinality which expects a singular input -- which is allowed to be
|
|
2045
|
+
* _undefined_ -- and maps to 0,
|
|
2046
|
+
* 1, or many outputs.
|
|
2140
2047
|
*/
|
|
2141
|
-
|
|
2142
|
-
|
|
2048
|
+
type CardinalityFilter0 = ZeroToOne | ZeroToMany | OneToOne | OneToMany | OneToZero | ZeroToZero;
|
|
2049
|
+
type CardinalityExplicit = `${number}:${number}`;
|
|
2143
2050
|
/**
|
|
2144
|
-
*
|
|
2145
|
-
*
|
|
2146
|
-
* A dictionary converted by `arrayToObject()` which expects each key `S` to have a only a
|
|
2147
|
-
* single/unique value.
|
|
2051
|
+
* Cardinality of any sort between two types
|
|
2148
2052
|
*/
|
|
2149
|
-
type
|
|
2150
|
-
|
|
2151
|
-
};
|
|
2053
|
+
type Cardinality = CardinalityFilter0 | CardinalityFilter1 | ManyToMany | ManyToOne | ManyToZero | CardinalityExplicit;
|
|
2054
|
+
type CardinalityTuple<T extends Cardinality> = UnionToTuple<T>;
|
|
2152
2055
|
/**
|
|
2153
|
-
*
|
|
2154
|
-
*
|
|
2155
|
-
* A dictionary converted by `arrayToObject()` which expects each key `S` to have an
|
|
2156
|
-
* array of values.
|
|
2056
|
+
* The first or _input_ part of the Cardinality relationship
|
|
2157
2057
|
*/
|
|
2158
|
-
type
|
|
2159
|
-
[V in T as V[S]]: V[];
|
|
2160
|
-
};
|
|
2161
|
-
type ArrayConverter<S extends PropertyKey, U extends boolean> =
|
|
2058
|
+
type CardinalityIn<T extends Cardinality> = T extends `${infer IN}:${string}` ? IN : never;
|
|
2162
2059
|
/**
|
|
2163
|
-
*
|
|
2164
|
-
* utility. At this point, the configuration is setup already and all that's
|
|
2165
|
-
* left is to pass in an array of objects.
|
|
2060
|
+
* The second or _output_ part of the Cardinality relationship
|
|
2166
2061
|
*/
|
|
2167
|
-
<
|
|
2062
|
+
type CardinalityOut<T extends Cardinality> = T extends `${string}:${infer OUT}` ? OUT : never;
|
|
2063
|
+
type CardinalityInput<T, C extends Cardinality> = CardinalityTuple<C>[0] extends 0 ? T | undefined : CardinalityTuple<C>[0] extends 1 ? T : T[];
|
|
2064
|
+
|
|
2168
2065
|
/**
|
|
2169
|
-
* Converts
|
|
2170
|
-
* by all objects and using that as the key to the dictionary.
|
|
2066
|
+
* Converts a string literal into a _dasherized_ format while ignoring _exterior_ whitespace.
|
|
2171
2067
|
*
|
|
2172
2068
|
* ```ts
|
|
2173
|
-
*
|
|
2174
|
-
*
|
|
2175
|
-
*
|
|
2176
|
-
*
|
|
2177
|
-
*
|
|
2069
|
+
* // "foo-bar"
|
|
2070
|
+
* type Dash = Dasherize<"foo_bar">;
|
|
2071
|
+
* type Dash = Dasherize<"fooBar">;
|
|
2072
|
+
* type Dash = Dasherize<"FooBar">;
|
|
2073
|
+
* // "\n foo-bar \t"
|
|
2074
|
+
* type Dash = Dasherize<"\n foo bar \t">;
|
|
2178
2075
|
* ```
|
|
2179
|
-
*
|
|
2180
|
-
* This will produce a dictionary with keys of `color` and `song`.
|
|
2181
2076
|
*/
|
|
2182
|
-
|
|
2077
|
+
type Dasherize<S extends string> = string extends S ? string : DashUppercase<Trim<LowerAllCaps<S>>> extends `${infer Begin}${"_" | " "}${infer Rest}` ? Dasherize<`${Lowercase<Begin>}-${Rest}`> : Lowercase<DashUppercase<Uncapitalize<Trim<LowerAllCaps<S>>>>>;
|
|
2183
2078
|
|
|
2184
|
-
interface Box<T> {
|
|
2185
|
-
__kind: "box";
|
|
2186
|
-
value: T;
|
|
2187
|
-
/**
|
|
2188
|
-
* Unbox the boxed value in the narrowest possible type.
|
|
2189
|
-
*
|
|
2190
|
-
* **Note:** _if you want a wider type definition use `wide()`
|
|
2191
|
-
* instead._
|
|
2192
|
-
*/
|
|
2193
|
-
unbox(): T;
|
|
2194
|
-
}
|
|
2195
|
-
type BoxValue<T extends Box<any>> = T extends Box<infer V> ? V : never;
|
|
2196
|
-
type BoxedFnParams<T extends Box<any>> = T extends Box<infer V> ? V extends (...args: infer A) => any ? A : [] : [];
|
|
2197
|
-
type BoxedReturn<T extends Box<any>> = T extends Box<infer V> ? V extends Function ? ReturnType<T["value"]> : T["value"] : never;
|
|
2198
|
-
type NarrowBox<T> = <N extends BoxedFnParams<Box<T>> | First<BoxedFnParams<Box<T>>>>() => N extends BoxedFnParams<Box<T>> ? T extends (...args: any[]) => any ? (...args: N) => Box<T>["unbox"] : never : (first: N, ...rest: AfterFirst<BoxedFnParams<Box<T>>>) => BoxedReturn<Box<T>>;
|
|
2199
2079
|
/**
|
|
2200
|
-
*
|
|
2201
|
-
* so that this type inference is preserved with the help of
|
|
2202
|
-
* [instantiation expressions](https://devblogs.microsoft.com/typescript/announcing-typescript-4-7-beta/#instantiation-expressions).
|
|
2080
|
+
* **EnsureLeading**`<T, U>`
|
|
2203
2081
|
*
|
|
2204
|
-
*
|
|
2082
|
+
* Will ensure that `T` ends with the _substring_ `U` when
|
|
2083
|
+
* both are string literals.
|
|
2084
|
+
*
|
|
2085
|
+
* ```ts
|
|
2086
|
+
* type T = " World";
|
|
2087
|
+
* type U = "Hello";
|
|
2088
|
+
* // "Hello World"
|
|
2089
|
+
* type R = EnsureLeading<T,U>;
|
|
2090
|
+
* ```
|
|
2205
2091
|
*/
|
|
2206
|
-
|
|
2207
|
-
declare function isBox(thing: unknown): thing is Box<any>;
|
|
2208
|
-
type Unbox<T> = T extends Box<infer U> ? U : T;
|
|
2209
|
-
declare function unbox<T>(thing: T): Unbox<T>;
|
|
2092
|
+
type EnsureLeading<T extends string, U extends string> = IfLiteral<T, string extends U ? never : T extends `${U}${string}` ? T : `${U}${T}`, string>;
|
|
2210
2093
|
|
|
2211
2094
|
/**
|
|
2212
|
-
*
|
|
2095
|
+
* Returns true or false value based on whether the string literal is capitalized.
|
|
2096
|
+
* ```ts
|
|
2097
|
+
* // true
|
|
2098
|
+
* type T2 = IsCapitalized<"One">;
|
|
2099
|
+
* // false
|
|
2100
|
+
* type T1 = IsCapitalized<"one">;
|
|
2101
|
+
* // "unknown"
|
|
2102
|
+
* const a: string = "Hi";
|
|
2103
|
+
* type T3 = IsCapitalized<typeof a>;
|
|
2104
|
+
* ```
|
|
2213
2105
|
*
|
|
2214
|
-
*
|
|
2215
|
-
* 2. The _second_ dictionary is interpreted as a "wide" definition of prop types
|
|
2106
|
+
* Note: _if the value passed in is a "string" then the result will be "unknown"_
|
|
2216
2107
|
*/
|
|
2217
|
-
|
|
2108
|
+
type IsCapitalized<T extends string> = string extends T ? "unknown" : T extends Capitalize<T> ? true : false;
|
|
2218
2109
|
|
|
2219
2110
|
/**
|
|
2220
|
-
*
|
|
2221
|
-
*
|
|
2222
|
-
|
|
2223
|
-
|
|
2111
|
+
* **KebabCase<T>** is an _alias_ for **Dasherize<T>**.
|
|
2112
|
+
* ```ts
|
|
2113
|
+
* // "foo-bar"
|
|
2114
|
+
* type Kebab = KebabCase<"foo_bar">;
|
|
2115
|
+
* type Kebab = KebabCase<"fooBar">;
|
|
2116
|
+
* type Kebab = KebabCase<"FooBar">;
|
|
2117
|
+
* // "\n foo-bar \t"
|
|
2118
|
+
* type Kebab = KebabCase<"\n foo bar \t">;
|
|
2119
|
+
* ``` */
|
|
2120
|
+
type KebabCase<T extends string> = Dasherize<T>;
|
|
2224
2121
|
|
|
2122
|
+
type Consonant = "b" | "c" | "d" | "f" | "g" | "h" | "j" | "k" | "l" | "m" | "n" | "p" | "q" | "r" | "s" | "t" | "v" | "w" | "x" | "z" | "y";
|
|
2123
|
+
type Exceptions = "photo => photos" | "piano => pianos" | "halo => halos" | "foot => feet" | "man => men" | "woman => women" | "person => people" | "mouse => mice" | "series => series" | "sheep => sheep" | "money => monies" | "deer => deer";
|
|
2124
|
+
type SingularException<T = Exceptions> = T extends `${infer SINGULAR} => ${infer PLURAL}` ? SINGULAR : never;
|
|
2125
|
+
type PluralException<T extends SingularException, E extends Exceptions = Exceptions> = E extends `${T} => ${infer PLURAL}` ? PLURAL : never;
|
|
2126
|
+
type SingularNoun = "s" | "sh" | "ch" | "x" | "z" | "o";
|
|
2127
|
+
type F = "f" | "fe";
|
|
2128
|
+
type Y = `${Consonant}y`;
|
|
2129
|
+
type RemoveTrailingY<T> = T extends `${infer HEAD}y` ? HEAD : T;
|
|
2130
|
+
/** validates that a word ends with a pluralization exception */
|
|
2131
|
+
type isException<T extends string> = T extends SingularException ? T : never;
|
|
2132
|
+
/** validates that a string literal ends in "is" */
|
|
2133
|
+
type EndsIn_IS<T extends string> = T extends `${infer HEAD}is` ? T : never;
|
|
2134
|
+
/** validates that a string literal is a singular noun */
|
|
2135
|
+
type EndsInSingularNoun<T extends string> = T extends `${infer HEAD}${SingularNoun}` ? T : never;
|
|
2136
|
+
/** validates that a string literal ends in "f" or "fe" */
|
|
2137
|
+
type EndsIn_F<T extends string> = T extends `${infer HEAD}${F}` ? T : never;
|
|
2138
|
+
/** validates that a string literal ends a consonant followed by "y" */
|
|
2139
|
+
type EndsIn_Y<T extends string> = T extends `${infer HEAD}${Y}` ? T : never;
|
|
2225
2140
|
/**
|
|
2226
|
-
*
|
|
2227
|
-
* run-time content but with the _type_ of the `id` property being forced to a literal type
|
|
2141
|
+
* strings which end in the letters "is" should have an "es" added to the end
|
|
2228
2142
|
*/
|
|
2229
|
-
|
|
2230
|
-
id: I;
|
|
2231
|
-
}, I extends PropertyKey>(o: T): T & {
|
|
2232
|
-
id: T["id"];
|
|
2233
|
-
};
|
|
2143
|
+
type PluralizeEndingIn_IS<T extends string> = T extends `${infer HEAD}is` ? `${HEAD}ises` : T;
|
|
2234
2144
|
/**
|
|
2235
|
-
*
|
|
2236
|
-
* run-time content but with the _type_ of the `name` property being forced to a literal type
|
|
2145
|
+
* singular nouns should have "es" added to the end
|
|
2237
2146
|
*/
|
|
2238
|
-
|
|
2239
|
-
name: I;
|
|
2240
|
-
}, I extends PropertyKey>(o: T): T & {
|
|
2241
|
-
name: T["name"];
|
|
2242
|
-
};
|
|
2147
|
+
type PluralizeEndingSingularNoun<T extends string> = T extends `${infer HEAD}${SingularNoun}` ? `${T}es` : T;
|
|
2243
2148
|
/**
|
|
2244
|
-
*
|
|
2245
|
-
* run-time content but with the _type_ of the `kind` property being forced to a literal type
|
|
2149
|
+
* strings which end in the letters "f" or "fe" should have "ves" replace the ending
|
|
2246
2150
|
*/
|
|
2247
|
-
|
|
2248
|
-
kind: I;
|
|
2249
|
-
}, I extends PropertyKey>(o: T): T & {
|
|
2250
|
-
kind: T["kind"];
|
|
2251
|
-
};
|
|
2252
|
-
declare function idTypeGuard<T extends {
|
|
2253
|
-
id: I;
|
|
2254
|
-
}, I extends PropertyKey>(_o: T): _o is T & {
|
|
2255
|
-
id: I;
|
|
2256
|
-
};
|
|
2151
|
+
type PluralizeEnding_F<T extends string> = T extends `${infer HEAD}${F}` ? `${HEAD}ves` : T;
|
|
2257
2152
|
/**
|
|
2258
|
-
*
|
|
2259
|
-
* values on the object.
|
|
2260
|
-
*
|
|
2261
|
-
* > Note: this addresses this [a known TS gap](https://github.com/microsoft/TypeScript/issues/30680).
|
|
2262
|
-
* > Hopefully at some point this will be addressed in the language.
|
|
2153
|
+
* singular nouns should have "es" added to the end
|
|
2263
2154
|
*/
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
declare function stripEnding<T extends string, U extends string>(content: T, strip: U): StripEnding<T, U>;
|
|
2155
|
+
type PluralizeEndingIn_Y<T extends string> = T extends `${infer HEAD}${Y}` ? `${RemoveTrailingY<T>}ies` : T;
|
|
2156
|
+
type Pluralize<T extends string> = T extends isException<T> ? PluralException<T> : T extends EndsIn_IS<T> ? PluralizeEndingIn_IS<T> : T extends EndsInSingularNoun<T> ? PluralizeEndingSingularNoun<T> : T extends EndsIn_F<T> ? PluralizeEnding_F<T> : T extends EndsIn_Y<T> ? PluralizeEndingIn_Y<T> : `${T}s`;
|
|
2267
2157
|
|
|
2268
|
-
|
|
2158
|
+
/** convert space to dash */
|
|
2159
|
+
type SpaceToDash<T extends string> = T extends `${infer Begin}${" "}${infer Rest}` ? SpaceToDash<`${Begin}-${Rest}`> : T;
|
|
2160
|
+
/**
|
|
2161
|
+
* Converts a string literal type to _snake_case_.
|
|
2162
|
+
* ```ts
|
|
2163
|
+
* // "foo_bar"
|
|
2164
|
+
* type T = SnakeCase<"fooBar">;
|
|
2165
|
+
* type T = SnakeCase<"FooBar">;
|
|
2166
|
+
* type T = SnakeCase<"foo-bar">;
|
|
2167
|
+
* type T = SnakeCase<"\n foo bar \t">;
|
|
2168
|
+
* ``` */
|
|
2169
|
+
type SnakeCase<S extends string> = string extends S ? string : DashUppercase<Uncapitalize<SpaceToDash<Trim<LowerAllCaps<S>>>>> extends `${infer Begin}${"-"}${infer Rest}` ? SnakeCase<`${Lowercase<Begin>}_${Rest}`> : Lowercase<DashUppercase<Uncapitalize<Trim<LowerAllCaps<S>>>>>;
|
|
2269
2170
|
|
|
2270
2171
|
/**
|
|
2271
|
-
* **
|
|
2172
|
+
* **StripStarting**`<T, U>`
|
|
2272
2173
|
*
|
|
2273
|
-
*
|
|
2274
|
-
*
|
|
2275
|
-
*
|
|
2276
|
-
*
|
|
2174
|
+
* Will strip off of `T` the starting string defined by `U` when
|
|
2175
|
+
* both are string literals.
|
|
2176
|
+
* ```ts
|
|
2177
|
+
* type T = "Hello World";
|
|
2178
|
+
* type U = "Hello ";
|
|
2179
|
+
* // "World"
|
|
2180
|
+
* type R = StripStarting<T,U>;
|
|
2181
|
+
* ```
|
|
2277
2182
|
*/
|
|
2278
|
-
type
|
|
2183
|
+
type StripLeading<T extends string, U extends string> = IfLiteral<T, string extends U ? never : T extends `${U}${infer After}` ? After : T, string>;
|
|
2184
|
+
|
|
2185
|
+
type NetworkProtocol = "http" | "https" | "file" | "ws" | "wss";
|
|
2279
2186
|
/**
|
|
2280
|
-
*
|
|
2281
|
-
*
|
|
2282
|
-
* Type utility that helps to build a enumerated set
|
|
2283
|
-
* of numeric literals which _could_ be the value for
|
|
2284
|
-
* a number based property but _allows_ a number that
|
|
2285
|
-
* is not part of the suggestion to be typed in too.
|
|
2286
|
-
*/
|
|
2287
|
-
type SuggestNumeric<T extends number> = T | (number & {});
|
|
2288
|
-
|
|
2289
|
-
type Condition<TInput extends Narrowable, TResult extends boolean> = (input: TInput) => TResult;
|
|
2290
|
-
declare const condition: <TInput extends Narrowable, C extends Condition<Narrowable, boolean>>(c: C, input: TInput) => boolean;
|
|
2291
|
-
|
|
2292
|
-
declare function isArray<T>(i: T): IsArray<T>;
|
|
2293
|
-
/**
|
|
2294
|
-
* **ifArray**(T, IF, ELSE)
|
|
2295
|
-
*
|
|
2296
|
-
* A utility which evaluates a type `T` for whether it is an array and then
|
|
2297
|
-
*/
|
|
2298
|
-
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>;
|
|
2299
|
-
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>;
|
|
2300
|
-
|
|
2301
|
-
/**
|
|
2302
|
-
* Runtime and type checks whether a variable is a boolean value.
|
|
2303
|
-
*/
|
|
2304
|
-
declare function isBoolean<T extends any>(i: T): IsBoolean<T>;
|
|
2305
|
-
/**
|
|
2306
|
-
* **ifBoolean**
|
|
2307
|
-
*
|
|
2308
|
-
* Strongly type-aware conditional statement which checks whether a value is
|
|
2309
|
-
* a _boolean_ and returns one of two values (strongly typed) based on the evaluation
|
|
2310
|
-
* of this criteria.
|
|
2311
|
-
*
|
|
2312
|
-
* @param val the value being tested
|
|
2313
|
-
* @param ifVal the value (strongly typed) returned if val is _boolean_
|
|
2314
|
-
* @param elseVal the value (strongly typed) returned if val is NOT a _boolean
|
|
2315
|
-
*/
|
|
2316
|
-
declare function ifBoolean<T, IF, ELSE>(val: T, ifVal: IF, elseVal: ELSE): IsBoolean<T> extends true ? IF : ELSE;
|
|
2317
|
-
|
|
2318
|
-
declare function isFalse<T>(i: T): IsFalse<T>;
|
|
2319
|
-
/**
|
|
2320
|
-
* **ifTrue**
|
|
2321
|
-
*
|
|
2322
|
-
* Strongly type-aware conditional statement which checks whether a value is
|
|
2323
|
-
* a _true_ and returns one of two values (strongly typed) based on the evaluation
|
|
2324
|
-
* of this criteria.
|
|
2325
|
-
*
|
|
2326
|
-
* @param val the value being tested
|
|
2327
|
-
* @param ifVal the value (strongly typed) returned if val is _true_ value
|
|
2328
|
-
* @param elseVal the value (strongly typed) returned if val is NOT a _true_ value
|
|
2329
|
-
*
|
|
2330
|
-
* Note: at runtime there's no way to distinguish if the value was widely or loosely
|
|
2331
|
-
* typed so unlike the type utility there is no "MAYBE" state but if a wide type if
|
|
2332
|
-
* encountered the _type_ will the union of `IF` and `ELSE`.
|
|
2333
|
-
*/
|
|
2334
|
-
declare function ifFalse<T extends boolean, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifVal: IF, elseVal: ELSE): IfFalse<T, IF, ELSE, IF | ELSE>;
|
|
2335
|
-
|
|
2336
|
-
type IsFunction<T> = T extends FunctionType ? true : false;
|
|
2337
|
-
type HybridFunction<TProps extends {}> = (<TArgs extends any[]>(...args: TArgs) => any) & TProps;
|
|
2338
|
-
type SimpleFunction = <TArgs extends any[]>(...args: TArgs) => any;
|
|
2339
|
-
type AnyFunction<TProps extends {} | never = never> = TProps extends {} ? HybridFunction<TProps> : SimpleFunction;
|
|
2340
|
-
/**
|
|
2341
|
-
* Checks whether a passed in value is a function and ensures run-time and types
|
|
2342
|
-
* are consistent.
|
|
2343
|
-
* ```ts
|
|
2344
|
-
* // true
|
|
2345
|
-
* const yup = isFunction(() => "hello world");
|
|
2346
|
-
* ```
|
|
2347
|
-
*
|
|
2348
|
-
* Note: the runtime `typeof [variable]` will correctly say "function" when a function is
|
|
2349
|
-
* encountered but if that function also has object types defined then the type will be a big
|
|
2350
|
-
* and ugly union type. This function will give you a proper boolean value in both cases.
|
|
2187
|
+
* A literal variant of _string_ which is meant to represent a domain name
|
|
2188
|
+
* (e.g., `www.someplace.com`, etc.)
|
|
2351
2189
|
*/
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
type IsNull<T> = T extends null ? true : false;
|
|
2355
|
-
declare function isNull<T extends Narrowable>(i: T): T extends null ? true : false;
|
|
2190
|
+
type DomainName = `${AlphaNumeric}${string}.${AlphaNumeric}${string}` | `${AlphaNumeric}${string}.${AlphaNumeric}${string}.${string}` | `${AlphaNumeric}${string}.${AlphaNumeric}${string}.${string}.${string}`;
|
|
2191
|
+
type RelativeUrl = `${VariableName | "/"}`;
|
|
2356
2192
|
/**
|
|
2357
|
-
*
|
|
2358
|
-
*
|
|
2359
|
-
*
|
|
2360
|
-
* Null and returns one of two values (strongly typed) based on the evaluation
|
|
2361
|
-
* of this criteria.
|
|
2362
|
-
*
|
|
2363
|
-
* @param val the value being tested
|
|
2364
|
-
* @param ifVal the value (strongly typed) returned if val is `null`
|
|
2365
|
-
* @param elseVal the value (strongly typed) returned if val is NOT `null`
|
|
2193
|
+
* A literal variant of _string_ which forces a string to follow conventions
|
|
2194
|
+
* for a fully qualified URL like `https://google.com`. It can't ensure the
|
|
2195
|
+
* type is fully valid but does help to avoid some typos.
|
|
2366
2196
|
*/
|
|
2367
|
-
|
|
2197
|
+
type FullyQualifiedUrl = `${NetworkProtocol}://${Ipv4 | DomainName}/${string}`;
|
|
2198
|
+
type UrlBuilder = (<P extends NetworkProtocol, D extends DomainName, B extends RelativeUrl>(protocol: P, domain: D, basePath: B) => `${P}://${D}/${B}`) | (<U extends RelativeUrl>(url: U) => U);
|
|
2368
2199
|
|
|
2369
|
-
type IsNumber<T> = T extends number ? true : false;
|
|
2370
|
-
declare function isNumber<T>(i: T): T extends number ? true : false;
|
|
2371
2200
|
/**
|
|
2372
|
-
* **
|
|
2201
|
+
* **ensureLeading**(content, strip)
|
|
2373
2202
|
*
|
|
2374
|
-
*
|
|
2375
|
-
*
|
|
2376
|
-
* of this criteria.
|
|
2377
|
-
*
|
|
2378
|
-
* @param val the value being tested
|
|
2379
|
-
* @param ifVal the value (strongly typed) returned if val is number
|
|
2380
|
-
* @param elseVal the value (strongly typed) returned if val is NOT a number
|
|
2381
|
-
*/
|
|
2382
|
-
declare function ifNumber<T, IF, ELSE>(val: T, ifVal: IF, elseVal: ELSE): IsNumber<T> extends true ? IF : ELSE;
|
|
2383
|
-
|
|
2384
|
-
type ObjectType = Not<Record<string, Narrowable>, FunctionType>;
|
|
2385
|
-
/**
|
|
2386
|
-
* Detects whether the passed in `v` is of type "object" where an object
|
|
2387
|
-
* is defined to be a string keyed dictionary style object. This means that
|
|
2388
|
-
* arrays are excluded, as well as functions which also have properties hanging
|
|
2389
|
-
* off of them.
|
|
2203
|
+
* Runtime utility which ensures that last part of a string -- `content` -- has the
|
|
2204
|
+
* substring `ensure` at the end and adds it if not present.
|
|
2390
2205
|
*/
|
|
2391
|
-
declare function
|
|
2206
|
+
declare function ensureLeading<T extends string, U extends string>(content: T, ensure: U): EnsureLeading<T, U>;
|
|
2392
2207
|
|
|
2393
2208
|
/**
|
|
2394
|
-
* **
|
|
2209
|
+
* **Suggest**
|
|
2395
2210
|
*
|
|
2396
|
-
* Type utility
|
|
2397
|
-
* string
|
|
2211
|
+
* Type utility that helps to build a enumerated set
|
|
2212
|
+
* of string literals which _could_ be the value for
|
|
2213
|
+
* a string based property but _allows_ a string that
|
|
2214
|
+
* is not part of the suggestion to be typed in too.
|
|
2398
2215
|
*/
|
|
2399
|
-
type
|
|
2216
|
+
type Suggest<T extends string> = T | (string & {});
|
|
2400
2217
|
/**
|
|
2401
|
-
* **
|
|
2218
|
+
* **SuggestNumeric**`<T>`
|
|
2402
2219
|
*
|
|
2403
|
-
* Type utility
|
|
2404
|
-
*
|
|
2220
|
+
* Type utility that helps to build a enumerated set
|
|
2221
|
+
* of numeric literals which _could_ be the value for
|
|
2222
|
+
* a number based property but _allows_ a number that
|
|
2223
|
+
* is not part of the suggestion to be typed in too.
|
|
2405
2224
|
*/
|
|
2406
|
-
type
|
|
2407
|
-
IF extends Narrowable, ELSE extends Narrowable> = IsString<T> extends true ? IF : IsString<T> extends false ? ELSE : IF | ELSE;
|
|
2225
|
+
type SuggestNumeric<T extends number> = T | (number & {});
|
|
2408
2226
|
|
|
2409
2227
|
/**
|
|
2410
|
-
* **
|
|
2411
|
-
*
|
|
2412
|
-
* Returns true or false on whether the passed in parameter is a
|
|
2413
|
-
* string (either a wide string or a string literal).
|
|
2414
|
-
*
|
|
2415
|
-
* The boolean return is traceable by the type system as well as the
|
|
2416
|
-
* runtime system.
|
|
2417
|
-
*/
|
|
2418
|
-
declare function isString<T>(i: T): IsString<T>;
|
|
2419
|
-
/**
|
|
2420
|
-
* **ifString**
|
|
2228
|
+
* **wide**
|
|
2421
2229
|
*
|
|
2422
|
-
*
|
|
2423
|
-
* a _string_ and returns one of two values (strongly typed) based on the evaluation
|
|
2424
|
-
* of this criteria.
|
|
2425
|
-
*
|
|
2426
|
-
* @param val the value being tested for being a string
|
|
2427
|
-
* @param ifVal the value (strongly typed) returned if val is _string_
|
|
2428
|
-
* @param elseVal the value (strongly typed) returned if val is NOT a _string
|
|
2230
|
+
* Provides a dictionary of _wide_ types
|
|
2429
2231
|
*/
|
|
2430
|
-
declare
|
|
2431
|
-
|
|
2432
|
-
|
|
2232
|
+
declare const wide: {
|
|
2233
|
+
readonly boolean: boolean;
|
|
2234
|
+
readonly string: string;
|
|
2235
|
+
readonly number: number;
|
|
2236
|
+
readonly symbol: Symbol;
|
|
2237
|
+
readonly null: null;
|
|
2238
|
+
readonly undefined: undefined;
|
|
2239
|
+
};
|
|
2433
2240
|
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
*/
|
|
2437
|
-
declare function isTrue<T extends Narrowable>(i: T): IsTrue<T>;
|
|
2438
|
-
/**
|
|
2439
|
-
* **ifTrue**
|
|
2440
|
-
*
|
|
2441
|
-
* Strongly type-aware conditional statement which checks whether a value is
|
|
2442
|
-
* _true_.
|
|
2443
|
-
*
|
|
2444
|
-
* @param val the value being tested
|
|
2445
|
-
* @param ifVal the value (strongly typed) returned if val is _true_ value
|
|
2446
|
-
* @param elseVal the value (strongly typed) returned if val is NOT a _true_ value
|
|
2447
|
-
*
|
|
2448
|
-
* Note: at runtime there's no way to distinguish if the value was widely or loosely
|
|
2449
|
-
* typed so unlike the type utility there is no "MAYBE" state but if a wide type if
|
|
2450
|
-
* encountered the _type_ will the union of `IF` and `ELSE`.
|
|
2451
|
-
*/
|
|
2452
|
-
declare function ifTrue<T extends boolean, IF extends Narrowable, ELSE extends Narrowable>(val: T, ifVal: IF, elseVal: ELSE): IfTrue<T, IF, ELSE, IF | ELSE>;
|
|
2241
|
+
type Condition<TInput extends Narrowable, TResult extends boolean> = (input: TInput) => TResult;
|
|
2242
|
+
declare const condition: <TInput extends Narrowable, C extends Condition<Narrowable, boolean>>(c: C, input: TInput) => boolean;
|
|
2453
2243
|
|
|
2454
|
-
declare function isUndefined<T extends Narrowable>(i: T): undefined extends T ? true : false;
|
|
2455
2244
|
/**
|
|
2456
|
-
* **
|
|
2457
|
-
*
|
|
2458
|
-
* Strongly type-aware conditional statement which checks whether a value is
|
|
2459
|
-
* _undefined_ and returns one of two values (strongly typed) based on the evaluation
|
|
2460
|
-
* of this criteria.
|
|
2245
|
+
* **TypeGuard**
|
|
2461
2246
|
*
|
|
2462
|
-
*
|
|
2463
|
-
*
|
|
2464
|
-
* @param elseVal the value (strongly typed) returned if val is NOT `undefined`
|
|
2247
|
+
* a typing for a **TS** type-guard which evaluates an _unknown_ input
|
|
2248
|
+
* and determines if it is of type `T`.
|
|
2465
2249
|
*/
|
|
2466
|
-
|
|
2250
|
+
type TypeGuard<T> = (thing: unknown) => thing is T;
|
|
2467
2251
|
|
|
2468
2252
|
type Type<T extends any, V extends Function> = {
|
|
2469
2253
|
name: string;
|
|
@@ -2573,4 +2357,360 @@ interface IFluentConfigurator<C> {
|
|
|
2573
2357
|
*/
|
|
2574
2358
|
declare function FluentConfigurator<I>(initial?: I): IFluentConfigurator<{}>;
|
|
2575
2359
|
|
|
2576
|
-
|
|
2360
|
+
type Widen<T> = T extends string ? string : T extends number ? number : T extends boolean ? boolean : T extends readonly string[] ? string[] : T extends readonly number[] ? number[] : T extends readonly boolean[] ? boolean[] : T extends readonly AnyFunction[] ? AnyFunction[] : T extends readonly any[] ? TupleToUnion<T>[] : T extends {} ? {} : T;
|
|
2361
|
+
|
|
2362
|
+
/**
|
|
2363
|
+
* **Includes**`<TSource, TValue>`
|
|
2364
|
+
*
|
|
2365
|
+
* Type utility which returns `true` or `false` based on whether `TValue` is found
|
|
2366
|
+
* in `TSource`. Where `TSource` can be a string literal or an array of string literals.
|
|
2367
|
+
*
|
|
2368
|
+
* **Note:** if the source is a _wide_ type (aka, `string` or `string[]`) then there is
|
|
2369
|
+
* no way to know at design-time whether the value includes `TValue` and so it will return
|
|
2370
|
+
* a type of `boolean`.
|
|
2371
|
+
*/
|
|
2372
|
+
type Includes<TSource extends string | readonly string[], TValue extends string> = TSource extends string[] ? IsStringLiteral<TupleToUnion<TSource>> extends true ? IsLiteral<TValue> extends true ? TValue extends TupleToUnion<TSource> ? true : false : boolean : boolean : TSource extends string ? IsLiteral<TSource> extends true ? IsLiteral<TValue> extends true ? TSource extends `${string}${TValue}${string}` ? true : false : boolean : boolean : boolean;
|
|
2373
|
+
|
|
2374
|
+
type IsScalar<T extends Narrowable> = [T] extends [string] ? true : [T] extends [number] ? true : [T] extends [boolean] ? true : false;
|
|
2375
|
+
/**
|
|
2376
|
+
* **IfScalar**`<T, IF, ELSE>`
|
|
2377
|
+
*
|
|
2378
|
+
* Branch type utility which returns `IF` when `T` is a scalar value (aka, string, number, or boolean) and `ELSE` otherwise
|
|
2379
|
+
*/
|
|
2380
|
+
type IfScalar<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable> = IsScalar<T> extends true ? IF : ELSE;
|
|
2381
|
+
|
|
2382
|
+
/**
|
|
2383
|
+
* **HasParameters**`<T>`
|
|
2384
|
+
*
|
|
2385
|
+
* Type utility which detects if `T` is both a function and whether that
|
|
2386
|
+
* function has at least one type parameter.
|
|
2387
|
+
* ```ts
|
|
2388
|
+
* const fn = (foo: string) => `${foo}bar`;
|
|
2389
|
+
* // true
|
|
2390
|
+
* type P = HasParameters<typeof fn>;
|
|
2391
|
+
* ```
|
|
2392
|
+
*/
|
|
2393
|
+
type HasParameters<T extends Narrowable> = T extends AnyFunction ? IsEqual<Length<Parameters<T>>, 0> extends true ? false : true : false;
|
|
2394
|
+
|
|
2395
|
+
/**
|
|
2396
|
+
* **IsObject**
|
|
2397
|
+
*
|
|
2398
|
+
* Boolean type utility used to check whether a type `T` is an object
|
|
2399
|
+
*/
|
|
2400
|
+
type IsObject<T> = Mutable<T> extends Record<string, any> ? T extends FunctionType ? false : Mutable<T> extends any[] ? false : true : false;
|
|
2401
|
+
/**
|
|
2402
|
+
* **IfObject**
|
|
2403
|
+
*
|
|
2404
|
+
* Branch type utility with return `IF` when `T` extends an object type
|
|
2405
|
+
* and `ELSE` otherwise
|
|
2406
|
+
*/
|
|
2407
|
+
type IfObject<T, IF extends Narrowable, ELSE extends Narrowable> = IsObject<T> extends true ? IF : ELSE;
|
|
2408
|
+
|
|
2409
|
+
/**
|
|
2410
|
+
* **StartsWith**<TValue, TStartsWith>
|
|
2411
|
+
*
|
|
2412
|
+
* A type utility which checks whether `T` _starts with_ the string literal `U`.
|
|
2413
|
+
*
|
|
2414
|
+
* If both `T` and `U` are string literals then the type system will resolve
|
|
2415
|
+
* to a literal `true` or `false` but if either is not a literal that it will
|
|
2416
|
+
* just resolve to `boolean` as the value can not be known at design time..
|
|
2417
|
+
*/
|
|
2418
|
+
type StartsWith<TValue extends string, TStartsWith extends string> = IsStringLiteral<TStartsWith> extends true ? IsStringLiteral<TValue> extends true ? TValue extends `${TStartsWith}${string}` ? true : false : boolean : boolean;
|
|
2419
|
+
/**
|
|
2420
|
+
* **IfStartsWith**<TValue, TStartsWith, IF, ELSE, MAYBE>
|
|
2421
|
+
*
|
|
2422
|
+
* Type utility which converts type to `IF` type _if_ TValue _starts with_ `TStartsWith` but
|
|
2423
|
+
* otherwise converts type to `ELSE`.
|
|
2424
|
+
*
|
|
2425
|
+
* Note, that there is also an optional `MAYBE` type
|
|
2426
|
+
* which can be stated for cases where TValue or TStartsWith _might_ be the wider `string`
|
|
2427
|
+
* type and therefore the type is unknown at design time.
|
|
2428
|
+
*/
|
|
2429
|
+
type IfStartsWith<TValue extends string, TStartsWith extends string, IF extends Narrowable, ELSE extends Narrowable> = StartsWith<TValue, TStartsWith> extends true ? IF : StartsWith<TValue, TStartsWith> extends false ? ELSE : IF | ELSE;
|
|
2430
|
+
|
|
2431
|
+
/**
|
|
2432
|
+
* **EndsWith**<T,U>
|
|
2433
|
+
*
|
|
2434
|
+
* A type utility which checks whether `T` _ends with_ the string literal `U`.
|
|
2435
|
+
*
|
|
2436
|
+
* If both `T` and `U` are string literals then the type system will resolve
|
|
2437
|
+
* to a literal `true` or `false` but if either is not a literal that it will
|
|
2438
|
+
* just resolve to `boolean` as the value can not be known at design time..
|
|
2439
|
+
*/
|
|
2440
|
+
type EndsWith<TValue extends string, TEndsWith extends string> = IsStringLiteral<TEndsWith> extends true ? IsStringLiteral<TValue> extends true ? TValue extends `${string}${TEndsWith}` ? true : false : boolean : boolean;
|
|
2441
|
+
/**
|
|
2442
|
+
* **IfEndsWith**<TValue, TEndsWith, IF, ELSE, MAYBE>
|
|
2443
|
+
*
|
|
2444
|
+
* Type utility which converts type to `IF` type _if_ `TValue` _ends with_ `TEndsWith` but
|
|
2445
|
+
* otherwise converts type to `ELSE`. If there are wide types in the mix then the type will
|
|
2446
|
+
* result in the union of IF and ELSE.
|
|
2447
|
+
*/
|
|
2448
|
+
type IfEndsWith<TValue extends string, TEndsWith extends string, IF extends Narrowable, ELSE extends Narrowable> = EndsWith<TValue, TEndsWith> extends true ? IF : EndsWith<TValue, TEndsWith> extends false ? ELSE : IF | ELSE;
|
|
2449
|
+
|
|
2450
|
+
/**
|
|
2451
|
+
* Makes a readonly structure mutable
|
|
2452
|
+
*/
|
|
2453
|
+
type Mutable<T> = {
|
|
2454
|
+
-readonly [K in keyof T]: IsObject<T[K]> extends true ? Mutable<T[K]> : T[K];
|
|
2455
|
+
};
|
|
2456
|
+
|
|
2457
|
+
/**
|
|
2458
|
+
* Provides a negation of a type of the type `T` _not_ `U`.
|
|
2459
|
+
* ```ts
|
|
2460
|
+
* const foo = 42;
|
|
2461
|
+
* // 33
|
|
2462
|
+
* type NotTheMeaningOfLife = Not<33, 42>;
|
|
2463
|
+
* // never
|
|
2464
|
+
* type NotTheMeaningOfLife = Not<42, 42>;
|
|
2465
|
+
* ```
|
|
2466
|
+
*
|
|
2467
|
+
* Note: same as `Exclude`
|
|
2468
|
+
*/
|
|
2469
|
+
type Not<T, U> = T extends U ? never : T;
|
|
2470
|
+
|
|
2471
|
+
type Digital = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
|
|
2472
|
+
type MakeArray<S extends string, T extends any[] = []> = S extends `${T["length"]}` ? T : MakeArray<S, [...T, 0]>;
|
|
2473
|
+
type Multiply10<T extends any[]> = [...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T, ...T];
|
|
2474
|
+
/**
|
|
2475
|
+
* Converts a string literal to a numeric literal
|
|
2476
|
+
* ```ts
|
|
2477
|
+
* // 0
|
|
2478
|
+
* type Zero = Numeric<"0">;
|
|
2479
|
+
* // 10
|
|
2480
|
+
* type Ten = Numeric<"10">;
|
|
2481
|
+
* ```
|
|
2482
|
+
*/
|
|
2483
|
+
type Numeric<S extends string, T extends any[] = []> = S extends `${infer S1}${infer S2}` ? S1 extends Digital ? Numeric<S2, [...Multiply10<T>, ...MakeArray<S1>]> : never : T["length"];
|
|
2484
|
+
|
|
2485
|
+
/**
|
|
2486
|
+
* **Opaque**
|
|
2487
|
+
*
|
|
2488
|
+
* Create an opaque type, which hides its internal details from the public, and
|
|
2489
|
+
* can only be created by being used explicitly.
|
|
2490
|
+
*
|
|
2491
|
+
* Note: taken from [type-fest](https://github.com/sindresorhus/type-fest/blob/main/source/opaque.d.ts)
|
|
2492
|
+
* repo.
|
|
2493
|
+
*/
|
|
2494
|
+
type Opaque<Type, Token = unknown> = Type & {
|
|
2495
|
+
readonly __opaque__: Token;
|
|
2496
|
+
};
|
|
2497
|
+
|
|
2498
|
+
/**
|
|
2499
|
+
* **Retain<T, K>**
|
|
2500
|
+
*
|
|
2501
|
+
* Reduces the type system to just the key/values which are represented in `K`.
|
|
2502
|
+
* The `L` generic can largely be ignored unless you need _literal_ equality.
|
|
2503
|
+
*
|
|
2504
|
+
* ```ts
|
|
2505
|
+
* type Obj = { foo: 1, bar: number, baz: string };
|
|
2506
|
+
* // { foo: 1, bar: number }
|
|
2507
|
+
* type Retained = Retain<Obj, "foo" | "bar">;
|
|
2508
|
+
* ```
|
|
2509
|
+
*
|
|
2510
|
+
* **Note:** in essence this is the _opposite_ of `Exclude<T,K>`
|
|
2511
|
+
*/
|
|
2512
|
+
type Retain<T, K extends keyof T> = Pick<T, Include<keyof T, K>>;
|
|
2513
|
+
|
|
2514
|
+
/**
|
|
2515
|
+
* Allows filtering down `T` to those which extend a given type `U`.
|
|
2516
|
+
*
|
|
2517
|
+
* - `T` is either a dictionary (where keys will be used to compare) or
|
|
2518
|
+
* a readonly sting array.
|
|
2519
|
+
* ```ts
|
|
2520
|
+
* const arr = ["foo", "bar", "baz"];
|
|
2521
|
+
* // "bar" | "baz"
|
|
2522
|
+
* type BA = Where<typeof arr, `ba${string}`>;
|
|
2523
|
+
* ```
|
|
2524
|
+
*/
|
|
2525
|
+
type Where<T extends Record<string, any> | readonly string[], U> = T extends readonly string[] ? Include<T[number], U> : {
|
|
2526
|
+
[K in keyof T]: K extends U ? K : never;
|
|
2527
|
+
}[keyof T];
|
|
2528
|
+
/**
|
|
2529
|
+
* Allows filtering down `T` to those which extend a given type `U`.
|
|
2530
|
+
*
|
|
2531
|
+
* - `T` is either a dictionary (where keys will be used to compare) or
|
|
2532
|
+
* a readonly sting array.
|
|
2533
|
+
* ```ts
|
|
2534
|
+
* const arr = ["foo", "bar", "baz"];
|
|
2535
|
+
* // "foo"
|
|
2536
|
+
* type F = WhereNot<typeof arr, `ba${string}`>;
|
|
2537
|
+
* ```
|
|
2538
|
+
*/
|
|
2539
|
+
type WhereNot<T extends Record<string, any> | readonly string[], U> = T extends readonly string[] ? Exclude<T[number], U> : {
|
|
2540
|
+
[K in keyof T]: K extends U ? never : K;
|
|
2541
|
+
}[keyof T];
|
|
2542
|
+
|
|
2543
|
+
type AppendToObject<T, U extends keyof any, V> = {
|
|
2544
|
+
[K in keyof T | U]: K extends keyof T ? T[K] : V;
|
|
2545
|
+
};
|
|
2546
|
+
/**
|
|
2547
|
+
* Appends a new Key/Value to an existing dictionary <T>
|
|
2548
|
+
*/
|
|
2549
|
+
type AppendToDictionary<TDict, TKey extends string, TValue> = {
|
|
2550
|
+
[K in keyof TDict | TKey]: K extends keyof TDict ? TDict[K] : TValue;
|
|
2551
|
+
};
|
|
2552
|
+
|
|
2553
|
+
/**
|
|
2554
|
+
* Accepts the `true` literal or _undefined_.
|
|
2555
|
+
*/
|
|
2556
|
+
type MaybeTrue = true | undefined;
|
|
2557
|
+
/**
|
|
2558
|
+
* Accepts the `false` literal or _undefined_.
|
|
2559
|
+
*/
|
|
2560
|
+
type MaybeFalse = false | undefined;
|
|
2561
|
+
|
|
2562
|
+
/**
|
|
2563
|
+
* A conditional clause used in the application of the `ifTypeOf` utility
|
|
2564
|
+
*/
|
|
2565
|
+
type ExtendsClause<N extends Narrowable, TValue extends Record<keyof TValue, N> | number | string | boolean | symbol> = <TBase extends any>(base: TBase) => TValue extends TBase ? true : false;
|
|
2566
|
+
/**
|
|
2567
|
+
* A conditional clause used in the application of the `ifTypeOf` utility
|
|
2568
|
+
*/
|
|
2569
|
+
type ExtendsNarrowlyClause<N extends Narrowable, TValue extends Record<keyof TValue, N> | number | string | boolean | symbol> = <NB extends Narrowable, TBase extends Record<keyof TBase, NB> | number | string | boolean | symbol>(base: TBase) => TValue extends TBase ? true : false;
|
|
2570
|
+
/**
|
|
2571
|
+
* **TypeCondition**
|
|
2572
|
+
*
|
|
2573
|
+
* A partially applied type from the `ifTypeOf` utility where the base type has been
|
|
2574
|
+
* defined and we now need to express the type which is intended to extend it.
|
|
2575
|
+
*
|
|
2576
|
+
* - `extends` - compares with _wide_ types
|
|
2577
|
+
* - `narrowlyExtends` - compares with _narrow_ / _literal_ types
|
|
2578
|
+
*/
|
|
2579
|
+
type TypeCondition<N extends Narrowable, TValue extends Record<keyof TValue, N> | number | string | boolean | symbol> = {
|
|
2580
|
+
extends: ExtendsClause<N, TValue>;
|
|
2581
|
+
narrowlyExtends: ExtendsNarrowlyClause<N, TValue>;
|
|
2582
|
+
};
|
|
2583
|
+
|
|
2584
|
+
/**
|
|
2585
|
+
* **RuleDefinition**
|
|
2586
|
+
*
|
|
2587
|
+
* A rule definition is the typing for the fluent API surface that is built up
|
|
2588
|
+
* with the **ruleset** utility.
|
|
2589
|
+
*/
|
|
2590
|
+
type RuleDefinition<
|
|
2591
|
+
/** the data which will be evaluated on rule execution */
|
|
2592
|
+
T extends object,
|
|
2593
|
+
/** the optional props -- as a union type -- which must be defined per the rule */
|
|
2594
|
+
H extends string = "",
|
|
2595
|
+
/** the key/values which will be evaluated on execution (wide type) */
|
|
2596
|
+
E extends Partial<SameKeys<T>> = {},
|
|
2597
|
+
/** the key/values which will be evaluated on execution (narrow type) */
|
|
2598
|
+
N extends Partial<SameKeys<T>> = {}> = {
|
|
2599
|
+
/**
|
|
2600
|
+
* sets up a true/false check that a given property is defined; this
|
|
2601
|
+
* condition can only be applied to _optional_ properties.
|
|
2602
|
+
*/
|
|
2603
|
+
has(optProp: OptionalKeys<T>): RuleDefinition<T, H & typeof optProp, E, N>;
|
|
2604
|
+
/**
|
|
2605
|
+
* Validates that a given property extends a certain value's type; comparison
|
|
2606
|
+
* is made assuming "wide types".
|
|
2607
|
+
*/
|
|
2608
|
+
equals<K extends keyof T, V extends Pick<T, K>>(prop: K, value: V): RuleDefinition<T, H, E & Record<K, V>, N>;
|
|
2609
|
+
/**
|
|
2610
|
+
* Validates that a given property extends a certain value's type; comparison
|
|
2611
|
+
* is made assuming "narrow types". This is only available for props which
|
|
2612
|
+
* expose a
|
|
2613
|
+
*/
|
|
2614
|
+
narrowlyEquals<K extends keyof T, V extends Pick<T, K>>(prop: K, value: V): RuleDefinition<T, H, E, N & Record<K, V>>;
|
|
2615
|
+
};
|
|
2616
|
+
/**
|
|
2617
|
+
* **DynamicRule**
|
|
2618
|
+
*
|
|
2619
|
+
* A dynamic rule allows type and runtime validation of a data structure
|
|
2620
|
+
* which extends a known `State`. It then returns the literal type `true`
|
|
2621
|
+
* or `false`.
|
|
2622
|
+
*
|
|
2623
|
+
* ```ts
|
|
2624
|
+
* type State = { id?: string; favorite: boolean; color: string };
|
|
2625
|
+
* // type-safe way to check whether optional prop is actually set
|
|
2626
|
+
* const rule: DynamicRule<State> = s => s
|
|
2627
|
+
* .has("id")
|
|
2628
|
+
* .equals("favorite", true)
|
|
2629
|
+
* .equals("color", "red");
|
|
2630
|
+
* ```
|
|
2631
|
+
*/
|
|
2632
|
+
type DynamicRule<TState extends any, TResult extends true | false> = (rule: TypeCondition<any, TState>) => TResult;
|
|
2633
|
+
/**
|
|
2634
|
+
* **DynamicRuleSet**
|
|
2635
|
+
*
|
|
2636
|
+
* A function which accepts the agreed `TState` generic as input and returns a discrete
|
|
2637
|
+
* `true` or `false` value.
|
|
2638
|
+
*/
|
|
2639
|
+
type DynamicRuleSet<TState extends any, TRules extends Record<string, TypeCondition<any, TState>>> = (rules: TRules) => true | false;
|
|
2640
|
+
|
|
2641
|
+
type RuntimeType<T> = {
|
|
2642
|
+
__kind: "type";
|
|
2643
|
+
type: T;
|
|
2644
|
+
is: TypeGuard<T>;
|
|
2645
|
+
};
|
|
2646
|
+
type RuntimeProp<P extends Readonly<PropertyKey>, T extends RuntimeType<any>> = {
|
|
2647
|
+
__kind: "prop";
|
|
2648
|
+
key: Readonly<P>;
|
|
2649
|
+
valueType: Readonly<T["type"]>;
|
|
2650
|
+
/**
|
|
2651
|
+
* Provides the _type_ to the type system when used with `typeof`.
|
|
2652
|
+
*
|
|
2653
|
+
* ```ts
|
|
2654
|
+
* const t = number();
|
|
2655
|
+
* // number
|
|
2656
|
+
* type T = typeof t.type;
|
|
2657
|
+
* ```
|
|
2658
|
+
*
|
|
2659
|
+
* **Note:** _the runtime system will get a string equivalent name:_
|
|
2660
|
+
* ```ts
|
|
2661
|
+
* const t = number();
|
|
2662
|
+
* // "number"
|
|
2663
|
+
* console.log(t.type);
|
|
2664
|
+
* ```
|
|
2665
|
+
*/
|
|
2666
|
+
type: Record<P, T["type"]>;
|
|
2667
|
+
is: TypeGuard<Record<P, T["type"]>>;
|
|
2668
|
+
};
|
|
2669
|
+
type TypeOptions<T extends Partial<object> = {}> = {
|
|
2670
|
+
/** each type has a default type guard but you can override if you need to be more specific */
|
|
2671
|
+
typeGuard?: TypeGuard<T>;
|
|
2672
|
+
} & T;
|
|
2673
|
+
|
|
2674
|
+
/**
|
|
2675
|
+
* Validates that a given type extends another and returns `true` or `false` type
|
|
2676
|
+
*/
|
|
2677
|
+
type ExpectExtends<VALUE, EXPECTED> = EXPECTED extends VALUE ? true : false;
|
|
2678
|
+
/**
|
|
2679
|
+
* Validates that a given type extends another and returns `any` or `never` as a type
|
|
2680
|
+
*/
|
|
2681
|
+
type AssertExtends<VALUE, EXPECTED> = EXPECTED extends VALUE ? any : never;
|
|
2682
|
+
/**
|
|
2683
|
+
* Give a type `TValue` and a comparison type `TExtends`
|
|
2684
|
+
*/
|
|
2685
|
+
type IfExtendsThen<VALUE, EXPECTED, THEN> = EXPECTED extends VALUE ? THEN : never;
|
|
2686
|
+
|
|
2687
|
+
/**
|
|
2688
|
+
* **ToFluent**
|
|
2689
|
+
*
|
|
2690
|
+
* Converts the typing of a dictionary of functions into the same
|
|
2691
|
+
* function signatures but changes the return type to be the Fluent API.
|
|
2692
|
+
*
|
|
2693
|
+
* **Note:** this utility also allows a non-fluent API surface `X` to be included as
|
|
2694
|
+
* part of the API surface if this is desired.
|
|
2695
|
+
*/
|
|
2696
|
+
type ToFluent<T extends {
|
|
2697
|
+
[key: string]: (...args: any[]) => any;
|
|
2698
|
+
}, X extends object = {}> = {
|
|
2699
|
+
[K in keyof T]: (...args: Parameters<T[K]>) => ToFluent<T, X> & X;
|
|
2700
|
+
} & X;
|
|
2701
|
+
/**
|
|
2702
|
+
* A _pure_ Fluent API which promotes an API surface where _every_ API endpoint must be a function
|
|
2703
|
+
* which returns the same API surface.
|
|
2704
|
+
*
|
|
2705
|
+
* To provide value, this style of Fluent API will need to perform useful _side effects_ when functions
|
|
2706
|
+
* on the API surface are called as this structure does not provide any means to maintain an internal state
|
|
2707
|
+
* which can be returned later.
|
|
2708
|
+
*
|
|
2709
|
+
* **Note:** _if you prefer a Fluent API with means to _escape_ with an internally managed state then
|
|
2710
|
+
* you should prefer the use of the `FluentApi` type._
|
|
2711
|
+
*/
|
|
2712
|
+
type PureFluentApi<TApi extends Record<string, (...args: any[]) => PureFluentApi<TApi, any>>, TExclude extends string = ""> = {
|
|
2713
|
+
[P in keyof TApi]: (...args: Parameters<TApi[P]>) => PureFluentApi<Omit<TApi, TExclude>>;
|
|
2714
|
+
};
|
|
2715
|
+
|
|
2716
|
+
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, DictionaryWithoutValue, DomainName, DynamicRule, DynamicRuleSet, Email, EndsWith, EnsureLeading, EnsureTrailing, EnumValues, ExpandRecursively, ExpectExtends, ExplicitFunction, Extends, FilterContains, FilterDefn, FilterEnds, FilterEquals, FilterFn, FilterGreaterThan, FilterIs, FilterLessThan, FilterNotEqual, FilterStarts, FilterTuple, FinalReturn, FinalizedMapConfig, First, FirstKey, FirstKeyValue, FirstOfEach, FirstOrUndefined, FirstString, FluentConfigurator, FluentFunction, FnShape, FromDictArray, FullyQualifiedUrl, FunctionType, GeneralDictionary, Get, HasParameters, HasUppercase, HybridFunction, IConfigurator, IFluentConfigurator, If, IfArray, IfBooleanLiteral, IfEndsWith, IfExtends, IfExtendsThen, IfFalse, IfLiteral, IfNumericLiteral, IfObject, IfOptionalLiteral, IfReadonlyArray, IfScalar, IfStartsWith, IfStringLiteral, IfTrue, IfUndefined, Include, Includes, IntersectingKeys, Ipv4, IsArray, IsBoolean, IsBooleanLiteral, IsCapitalized, IsEqual, 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, StripLeading, StripTrailing, 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, boxDictionaryValues, condition, createConverter, createFnWithProps, defineProperties, defineType, dictArr, dictToKv, dictionaryTransform, ensureLeading, ensureTrailing, entries, filter, filterDictArray, fnWithProps, groupBy, idLiteral, idTypeGuard, identity, ifArray, ifArrayPartial, ifBoolean, ifDefined, ifFalse, ifNull, ifNumber, ifObject, ifSameType, 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, stripTrailing, type, typeApi, unbox, wide, withValue };
|