inferred-types 0.34.0 → 0.35.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/dist/index.d.ts +89 -39
- package/dist/index.js +16 -0
- package/dist/index.mjs +14 -0
- package/package.json +8 -8
- package/src/runtime/combinators/or.ts +1 -1
- package/src/runtime/literals/index.ts +2 -0
- package/src/runtime/literals/pathJoin.ts +17 -0
- package/src/runtime/literals/stripEnding.ts +9 -0
- package/src/runtime/literals/stripStarting.ts +15 -0
- package/src/runtime/type-checks/isFalse.ts +1 -1
- package/src/runtime/type-checks/isTrue.ts +2 -3
- package/src/runtime/type-checks/startsWith.ts +7 -9
- package/src/types/alphabetic/PathJoin.ts +40 -0
- package/src/types/alphabetic/StripEnding.ts +23 -0
- package/src/types/alphabetic/StripStarting.ts +23 -0
- package/src/types/alphabetic/index.ts +2 -0
- package/src/types/boolean-logic/EndsWith.ts +30 -12
- package/src/types/boolean-logic/Extends.ts +11 -2
- package/src/types/boolean-logic/Includes.ts +3 -4
- package/src/types/boolean-logic/IsLiteral.ts +51 -4
- package/src/types/boolean-logic/IsScalar.ts +10 -4
- package/src/types/boolean-logic/IsUndefined.ts +5 -1
- package/src/types/{combinators → boolean-logic}/Or.ts +1 -1
- package/src/types/boolean-logic/StartsWith.ts +12 -13
- package/src/types/boolean-logic/array.ts +1 -1
- package/src/types/boolean-logic/boolean.ts +22 -14
- package/src/types/{combinators → boolean-logic}/equivalency.ts +0 -0
- package/src/types/boolean-logic/index.ts +2 -2
- package/src/types/boolean-logic/object.ts +4 -1
- package/src/types/boolean-logic/string.ts +1 -1
- package/src/types/index.ts +0 -1
- package/src/types/lists/FilterTuple.ts +20 -0
- package/src/types/lists/index.ts +1 -0
- package/tests/literals/PathJoin.test.ts +87 -0
- package/tests/runtime/if-is.spec.ts +11 -4
- package/src/types/boolean-logic/IsNumericLiteral.ts +0 -16
- package/src/types/boolean-logic/IsStringLiteral.ts +0 -14
- package/src/types/combinators/index.ts +0 -2
package/dist/index.d.ts
CHANGED
|
@@ -166,6 +166,19 @@ type AfterFirst<T extends readonly any[]> = T extends readonly [any, ...any[]] ?
|
|
|
166
166
|
*/
|
|
167
167
|
type FirstString<T> = T extends [infer S extends string, ...unknown[]] ? S : never;
|
|
168
168
|
|
|
169
|
+
/**
|
|
170
|
+
* **FilterTuple**
|
|
171
|
+
*
|
|
172
|
+
* Allows a known tuple `T` to be _filtered down_ by eliminating all items
|
|
173
|
+
* in the Tuple that _extend_ type `F`
|
|
174
|
+
* ```ts
|
|
175
|
+
* type T = [1,"foo",3];
|
|
176
|
+
* // [1,3]
|
|
177
|
+
* type T2 = FilterTuple<T, string>;
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
type FilterTuple<TTuple extends any[] | readonly any[], TFilter, Result extends any[] = []> = TTuple extends [infer A, ...infer R] ? [A] extends [TFilter] ? FilterTuple<R, TFilter, Result> : FilterTuple<R, TFilter, [...Result, A]> : Result;
|
|
181
|
+
|
|
169
182
|
/**
|
|
170
183
|
* **Split**`<T, SEP>`
|
|
171
184
|
*
|
|
@@ -280,26 +293,26 @@ type IsFalse<T extends Narrowable> = IsBoolean<T> extends true ? T extends false
|
|
|
280
293
|
* to the IF, ELSE, or MAYBE generic types passed in where _maybe_ is when T
|
|
281
294
|
* is the wide type of `boolean`
|
|
282
295
|
*/
|
|
283
|
-
type IfTrue<T, IF, ELSE, MAYBE> = IsTrue<T> extends true ? IF : IsTrue<T> extends false ? ELSE : MAYBE;
|
|
296
|
+
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;
|
|
284
297
|
/**
|
|
285
298
|
* Type utility which checks for literal `false` value and then switches type
|
|
286
299
|
* to the IF, ELSE, or MAYBE generic types passed in where _maybe_ is when T
|
|
287
300
|
* is the wide type of `boolean`
|
|
288
301
|
*/
|
|
289
|
-
type IfFalse<T, IF, ELSE, MAYBE> = IsFalse<T> extends true ? IF : IsTrue<T> extends false ? ELSE : MAYBE;
|
|
302
|
+
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;
|
|
290
303
|
/**
|
|
291
304
|
* **IsBooleanLiteral**
|
|
292
305
|
*
|
|
293
306
|
* Type utility which returns true/false if the boolean value is a _boolean literal_ versus
|
|
294
307
|
* just the wider _boolean_ type.
|
|
295
308
|
*/
|
|
296
|
-
type IsBooleanLiteral<T extends
|
|
309
|
+
type IsBooleanLiteral<T extends Narrowable> = IsTrue<T> extends true ? true : IsFalse<T> extends true ? true : false;
|
|
297
310
|
/**
|
|
298
311
|
* **IfBooleanLiteral**
|
|
299
312
|
*
|
|
300
313
|
* Branch utility which returns `IF` type when `T` is a boolean literal and `ELSE` otherwise
|
|
301
314
|
*/
|
|
302
|
-
type IfBooleanLiteral<T extends boolean, IF, ELSE> = IsBooleanLiteral<T> extends true ? IF : ELSE;
|
|
315
|
+
type IfBooleanLiteral<T extends boolean, IF extends Narrowable, ELSE extends Narrowable> = IsBooleanLiteral<T> extends true ? IF : ELSE;
|
|
303
316
|
|
|
304
317
|
/**
|
|
305
318
|
* **IsStringLiteral**
|
|
@@ -307,14 +320,15 @@ type IfBooleanLiteral<T extends boolean, IF, ELSE> = IsBooleanLiteral<T> extends
|
|
|
307
320
|
* Type utility which returns true/false if the string a _string literal_ versus
|
|
308
321
|
* just the _string_ type.
|
|
309
322
|
*/
|
|
310
|
-
type IsStringLiteral<T> = [T] extends [string] ?
|
|
323
|
+
type IsStringLiteral<T extends Narrowable> = [T] extends [string] ? string extends T ? false : true : false;
|
|
311
324
|
/**
|
|
312
325
|
* **IfStringLiteral**
|
|
313
326
|
*
|
|
314
327
|
* Branch utility which returns `IF` type when `T` is a string literal and `ELSE` otherwise
|
|
315
328
|
*/
|
|
316
|
-
type IfStringLiteral<T, IF, ELSE
|
|
317
|
-
|
|
329
|
+
type IfStringLiteral<T extends string, IF extends Narrowable, ELSE extends Narrowable> = [
|
|
330
|
+
IsStringLiteral<T>
|
|
331
|
+
] extends [true] ? IF : ELSE;
|
|
318
332
|
/**
|
|
319
333
|
* **IsNumericLiteral**
|
|
320
334
|
*
|
|
@@ -327,8 +341,7 @@ type IsNumericLiteral<T extends number> = number extends T ? false : true;
|
|
|
327
341
|
*
|
|
328
342
|
* Branch utility which returns `IF` type when `T` is a numeric literal and `ELSE` otherwise
|
|
329
343
|
*/
|
|
330
|
-
type IfNumericLiteral<T extends number, IF, ELSE> = IsNumericLiteral<T> extends true ? IF : ELSE;
|
|
331
|
-
|
|
344
|
+
type IfNumericLiteral<T extends number, IF extends Narrowable, ELSE extends Narrowable> = IsNumericLiteral<T> extends true ? IF : ELSE;
|
|
332
345
|
/**
|
|
333
346
|
* **IsLiteral**
|
|
334
347
|
*
|
|
@@ -354,17 +367,17 @@ type IsOptionalLiteral<T> = [Exclude<T, undefined>] extends [string] ? IsStringL
|
|
|
354
367
|
*
|
|
355
368
|
* Branch type utility with return `IF` when `T` is a _literal_ value and `ELSE` otherwise
|
|
356
369
|
*/
|
|
357
|
-
type IfLiteral<T, IF, ELSE> = IsLiteral<T> extends true ? IF : ELSE;
|
|
370
|
+
type IfLiteral<T, IF extends Narrowable, ELSE extends Narrowable> = IsLiteral<T> extends true ? IF : ELSE;
|
|
358
371
|
/**
|
|
359
372
|
* **IfOptionalLiteral**
|
|
360
373
|
*
|
|
361
374
|
* Branch type utility with return `IF` when `T` is a _literal_ value (with possibly
|
|
362
375
|
* the inclusion of _undefined_); otherwise returns the type `ELSE`
|
|
363
376
|
*/
|
|
364
|
-
type IfOptionalLiteral<T, IF, ELSE> = IsOptionalLiteral<T> extends true ? IF : ELSE;
|
|
377
|
+
type IfOptionalLiteral<T, IF extends Narrowable, ELSE extends Narrowable> = IsOptionalLiteral<T> extends true ? IF : ELSE;
|
|
365
378
|
|
|
366
379
|
/**
|
|
367
|
-
* **Includes
|
|
380
|
+
* **Includes**`<TSource, TValue>`
|
|
368
381
|
*
|
|
369
382
|
* Type utility which returns `true` or `false` based on whether `TValue` is found
|
|
370
383
|
* in `TSource`. Where `TSource` can be a string literal or an array of string literals.
|
|
@@ -373,15 +386,15 @@ type IfOptionalLiteral<T, IF, ELSE> = IsOptionalLiteral<T> extends true ? IF : E
|
|
|
373
386
|
* no way to know at design-time whether the value includes `TValue` and so it will return
|
|
374
387
|
* a type of `boolean`.
|
|
375
388
|
*/
|
|
376
|
-
type Includes<TSource extends string | 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;
|
|
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;
|
|
377
390
|
|
|
378
|
-
type IsScalar<T> = [T] extends [string] ? true : [T] extends [number] ? true : [T] extends [boolean] ? true : false;
|
|
391
|
+
type IsScalar<T extends Narrowable> = [T] extends [string] ? true : [T] extends [number] ? true : [T] extends [boolean] ? true : false;
|
|
379
392
|
/**
|
|
380
|
-
* **IfScalar
|
|
393
|
+
* **IfScalar**`<T, IF, ELSE>`
|
|
381
394
|
*
|
|
382
|
-
* Branch type utility which returns `IF` when `T` is a scalar value and `ELSE` otherwise
|
|
395
|
+
* Branch type utility which returns `IF` when `T` is a scalar value (aka, string, number, or boolean) and `ELSE` otherwise
|
|
383
396
|
*/
|
|
384
|
-
type IfScalar<T, IF, ELSE> = IsScalar<T> extends true ? IF : ELSE;
|
|
397
|
+
type IfScalar<T extends Narrowable, IF extends Narrowable, ELSE extends Narrowable> = IsScalar<T> extends true ? IF : ELSE;
|
|
385
398
|
|
|
386
399
|
/**
|
|
387
400
|
* **IsUndefined**
|
|
@@ -395,21 +408,21 @@ type IsUndefined<T extends Narrowable> = T extends undefined ? true : false;
|
|
|
395
408
|
* Type utility which returns `IF` type when `T` is an _undefined_
|
|
396
409
|
* otherwise returns `ELSE` type.
|
|
397
410
|
*/
|
|
398
|
-
type IfUndefined<T, IF, ELSE> = IsUndefined<T> extends true ? IF : ELSE;
|
|
411
|
+
type IfUndefined<T, IF extends Narrowable, ELSE extends Narrowable> = IsUndefined<T> extends true ? IF : ELSE;
|
|
399
412
|
|
|
400
413
|
/**
|
|
401
414
|
* **Extends**`<T, EXTENDS>`
|
|
402
415
|
*
|
|
403
416
|
* Boolean type utility which returns `true` if `T` _extends_ `EXTENDS`.
|
|
404
417
|
*/
|
|
405
|
-
type Extends<T, EXTENDS> = T extends EXTENDS ? true : false;
|
|
418
|
+
type Extends<T extends Narrowable, EXTENDS extends Narrowable> = T extends EXTENDS ? true : false;
|
|
406
419
|
/**
|
|
407
420
|
* **IfExtends**
|
|
408
421
|
*
|
|
409
422
|
* Branching type utility which returns type `IF` when `E` _extends_ `T`; otherwise
|
|
410
423
|
* it will return the type `ELSE`.
|
|
411
424
|
*/
|
|
412
|
-
type IfExtends<
|
|
425
|
+
type IfExtends<T extends Narrowable, EXTENDS extends Narrowable, IF extends Narrowable, ELSE extends Narrowable> = Extends<T, EXTENDS> extends true ? IF : ELSE;
|
|
413
426
|
|
|
414
427
|
/**
|
|
415
428
|
* Often when mutating the shape of an object you will end up with the union of a number of
|
|
@@ -460,7 +473,7 @@ type IsObject<T> = Mutable<T> extends Record<string, any> ? T extends FunctionTy
|
|
|
460
473
|
* Branch type utility with return `IF` when `T` extends an object type
|
|
461
474
|
* and `ELSE` otherwise
|
|
462
475
|
*/
|
|
463
|
-
type IfObject<T, IF, ELSE> = IsObject<T> extends true ? IF : ELSE;
|
|
476
|
+
type IfObject<T, IF extends Narrowable, ELSE extends Narrowable> = IsObject<T> extends true ? IF : ELSE;
|
|
464
477
|
|
|
465
478
|
/**
|
|
466
479
|
* **StartsWith**<TValue, TStartsWith>
|
|
@@ -471,8 +484,7 @@ type IfObject<T, IF, ELSE> = IsObject<T> extends true ? IF : ELSE;
|
|
|
471
484
|
* to a literal `true` or `false` but if either is not a literal that it will
|
|
472
485
|
* just resolve to `boolean` as the value can not be known at design time..
|
|
473
486
|
*/
|
|
474
|
-
type StartsWith<TValue extends
|
|
475
|
-
IfStringLiteral<TStartsWith, true, boolean>, boolean> : IfStringLiteral<TValue, false, boolean> : false : false;
|
|
487
|
+
type StartsWith<TValue extends string, TStartsWith extends string> = IsStringLiteral<TStartsWith> extends true ? IsStringLiteral<TValue> extends true ? TValue extends `${TStartsWith}${string}` ? true : false : boolean : boolean;
|
|
476
488
|
/**
|
|
477
489
|
* **IfStartsWith**<TValue, TStartsWith, IF, ELSE, MAYBE>
|
|
478
490
|
*
|
|
@@ -483,7 +495,7 @@ IfStringLiteral<TStartsWith, true, boolean>, boolean> : IfStringLiteral<TValue,
|
|
|
483
495
|
* which can be stated for cases where TValue or TStartsWith _might_ be the wider `string`
|
|
484
496
|
* type and therefore the type is unknown at design time.
|
|
485
497
|
*/
|
|
486
|
-
type IfStartsWith<TValue extends
|
|
498
|
+
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;
|
|
487
499
|
|
|
488
500
|
/**
|
|
489
501
|
* **EndsWith**<T,U>
|
|
@@ -494,8 +506,22 @@ type IfStartsWith<TValue extends unknown, TStartsWith extends unknown, IF extend
|
|
|
494
506
|
* to a literal `true` or `false` but if either is not a literal that it will
|
|
495
507
|
* just resolve to `boolean` as the value can not be known at design time..
|
|
496
508
|
*/
|
|
497
|
-
type EndsWith<
|
|
498
|
-
|
|
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>
|
|
512
|
+
*
|
|
513
|
+
* Type utility which converts type to `IF` type _if_ `TValue` _ends with_ `TEndsWith` but
|
|
514
|
+
* otherwise converts type to `ELSE`. If there are wide types in the mix then the type will
|
|
515
|
+
* result in the union of IF and ELSE.
|
|
516
|
+
*/
|
|
517
|
+
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;
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* **Or**`<T>`
|
|
521
|
+
*
|
|
522
|
+
* Takes an array of boolean values and produces a boolean OR across these values
|
|
523
|
+
*/
|
|
524
|
+
type Or<T extends readonly boolean[]> = NarrowlyContains<true, T> extends true ? true : NarrowlyContains<boolean, T> extends true ? boolean : false;
|
|
499
525
|
|
|
500
526
|
/**
|
|
501
527
|
* Makes a readonly structure mutable
|
|
@@ -1231,6 +1257,34 @@ type SpaceToDash<T extends string> = T extends `${infer Begin}${" "}${infer Rest
|
|
|
1231
1257
|
* ``` */
|
|
1232
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>>>>>;
|
|
1233
1259
|
|
|
1260
|
+
/**
|
|
1261
|
+
* **StripStarting**`<T, U>`
|
|
1262
|
+
*
|
|
1263
|
+
* Will strip off of `T` the starting string defined by `U` when
|
|
1264
|
+
* both are string literals.
|
|
1265
|
+
* ```ts
|
|
1266
|
+
* type T = "Hello World";
|
|
1267
|
+
* type U = "Hello ";
|
|
1268
|
+
* // "World"
|
|
1269
|
+
* type R = StripStarting<T,U>;
|
|
1270
|
+
* ```
|
|
1271
|
+
*/
|
|
1272
|
+
type StripStarting<T extends string, U extends string> = IfLiteral<T, string extends U ? never : T extends `${U}${infer After}` ? After : T, string>;
|
|
1273
|
+
|
|
1274
|
+
/**
|
|
1275
|
+
* **StripEnding**`<T, U>`
|
|
1276
|
+
*
|
|
1277
|
+
* Will strip off of `T` the ending defined by `U` when
|
|
1278
|
+
* both are string literals.
|
|
1279
|
+
* ```ts
|
|
1280
|
+
* type T = "Hello World";
|
|
1281
|
+
* type U = " World";
|
|
1282
|
+
* // "Hello"
|
|
1283
|
+
* type R = StripEnding<T,U>;
|
|
1284
|
+
* ```
|
|
1285
|
+
*/
|
|
1286
|
+
type StripEnding<T extends string, U extends string> = IfLiteral<T, string extends U ? never : T extends `${infer Before}${U}` ? Before : T, string>;
|
|
1287
|
+
|
|
1234
1288
|
type NetworkProtocol = "http" | "https" | "file" | "ws" | "wss";
|
|
1235
1289
|
/**
|
|
1236
1290
|
* A literal variant of _string_ which is meant to represent a domain name
|
|
@@ -1698,13 +1752,6 @@ type KvFrom<T extends object> = Array<{
|
|
|
1698
1752
|
*/
|
|
1699
1753
|
type KvTuple<T, K extends keyof T> = [K, Record<K, T[K]>];
|
|
1700
1754
|
|
|
1701
|
-
/**
|
|
1702
|
-
* **Or**`<T>`
|
|
1703
|
-
*
|
|
1704
|
-
* Takes an array of boolean values and produces a boolean OR across these values
|
|
1705
|
-
*/
|
|
1706
|
-
type Or<T extends readonly boolean[]> = NarrowlyContains<true, T> extends true ? true : NarrowlyContains<boolean, T> extends true ? boolean : false;
|
|
1707
|
-
|
|
1708
1755
|
type DictArrayFilterCallback<K extends keyof T, T extends object, R extends true | false> = (key: K, value: Pick<T, K>) => R;
|
|
1709
1756
|
/**
|
|
1710
1757
|
* An element in a `DictArray` shaped as a two element tuple: `[key, kv]`.
|
|
@@ -2216,6 +2263,10 @@ declare function idTypeGuard<T extends {
|
|
|
2216
2263
|
*/
|
|
2217
2264
|
declare function literal<N extends Narrowable, T extends Record<keyof T, N>>(obj: T): T;
|
|
2218
2265
|
|
|
2266
|
+
declare function stripEnding<T extends string, U extends string>(content: T, strip: U): StripEnding<T, U>;
|
|
2267
|
+
|
|
2268
|
+
declare function stripStarting<T extends string, U extends string>(content: T, strip: U): StripStarting<T, U>;
|
|
2269
|
+
|
|
2219
2270
|
/**
|
|
2220
2271
|
* **Suggest**
|
|
2221
2272
|
*
|
|
@@ -2280,7 +2331,7 @@ declare function isFalse<T>(i: T): IsFalse<T>;
|
|
|
2280
2331
|
* typed so unlike the type utility there is no "MAYBE" state but if a wide type if
|
|
2281
2332
|
* encountered the _type_ will the union of `IF` and `ELSE`.
|
|
2282
2333
|
*/
|
|
2283
|
-
declare function ifFalse<T extends
|
|
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>;
|
|
2284
2335
|
|
|
2285
2336
|
type IsFunction<T> = T extends FunctionType ? true : false;
|
|
2286
2337
|
type HybridFunction<TProps extends {}> = (<TArgs extends any[]>(...args: TArgs) => any) & TProps;
|
|
@@ -2353,7 +2404,7 @@ type IsString<T> = T extends string ? true : false;
|
|
|
2353
2404
|
* returns `IF` type if it is, otherwise returns the type `ELSE`.
|
|
2354
2405
|
*/
|
|
2355
2406
|
type IfString<T extends Narrowable, //
|
|
2356
|
-
IF extends Narrowable, ELSE extends Narrowable> = IsString<T> extends true ? IF : ELSE;
|
|
2407
|
+
IF extends Narrowable, ELSE extends Narrowable> = IsString<T> extends true ? IF : IsString<T> extends false ? ELSE : IF | ELSE;
|
|
2357
2408
|
|
|
2358
2409
|
/**
|
|
2359
2410
|
* **isString**
|
|
@@ -2388,8 +2439,7 @@ declare function isTrue<T extends Narrowable>(i: T): IsTrue<T>;
|
|
|
2388
2439
|
* **ifTrue**
|
|
2389
2440
|
*
|
|
2390
2441
|
* Strongly type-aware conditional statement which checks whether a value is
|
|
2391
|
-
*
|
|
2392
|
-
* of this criteria.
|
|
2442
|
+
* _true_.
|
|
2393
2443
|
*
|
|
2394
2444
|
* @param val the value being tested
|
|
2395
2445
|
* @param ifVal the value (strongly typed) returned if val is _true_ value
|
|
@@ -2399,7 +2449,7 @@ declare function isTrue<T extends Narrowable>(i: T): IsTrue<T>;
|
|
|
2399
2449
|
* typed so unlike the type utility there is no "MAYBE" state but if a wide type if
|
|
2400
2450
|
* encountered the _type_ will the union of `IF` and `ELSE`.
|
|
2401
2451
|
*/
|
|
2402
|
-
declare function ifTrue<T extends
|
|
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>;
|
|
2403
2453
|
|
|
2404
2454
|
declare function isUndefined<T extends Narrowable>(i: T): undefined extends T ? true : false;
|
|
2405
2455
|
/**
|
|
@@ -2523,4 +2573,4 @@ interface IFluentConfigurator<C> {
|
|
|
2523
2573
|
*/
|
|
2524
2574
|
declare function FluentConfigurator<I>(initial?: I): IFluentConfigurator<{}>;
|
|
2525
2575
|
|
|
2526
|
-
export { AfterFirst, AllCaps, Alpha, AlphaNumeric, AnyFunction, Api, ApiFunction, ApiValue, AppendToDictionary, AppendToObject, ArrConcat, Array$1 as Array, ArrayConverter, AsArray, AsFinalizedConfig, AssertExtends, Box, BoxValue, BoxedFnParams, BoxedReturn, Bracket, Break, CamelCase, CapitalizeWords, Cardinality, Cardinality0, Cardinality1, CardinalityExplicit, CardinalityFilter0, CardinalityFilter1, CardinalityIn, CardinalityInput, CardinalityNode, CardinalityOut, CardinalityTuple, ClosingBracket, Condition, ConditionFilter, Configurator, ConfiguredMap, Constructor, Contains, DEFAULT_MANY_TO_ONE_MAPPING, DEFAULT_ONE_TO_MANY_MAPPING, DEFAULT_ONE_TO_ONE_MAPPING, DashToSnake, DashUppercase, Dasherize, DecomposeMapConfig, DefaultManyToOneMapping, DefaultOneToManyMapping, DefaultOneToOneMapping, DefinePropertiesApi, DictArrApi, DictArray, DictArrayFilterCallback, DictArrayKv, DictChangeValue, DictFromKv, DictKvTuple, DictPartialApplication, DictPrependWithFn, DictReturnValues, DomainName, DynamicRule, DynamicRuleSet, Email, EndsWith, EnumValues, Equal, ExpandRecursively, ExpectExtends, ExplicitFunction, Extends, FilterContains, FilterDefn, FilterEnds, FilterEquals, FilterFn, FilterGreaterThan, FilterIs, FilterLessThan, FilterNotEqual, FilterStarts, FinalReturn, FinalizedMapConfig, First, FirstKey, FirstKeyValue, FirstOfEach, FirstOrUndefined, FirstString, FluentConfigurator, FluentFunction, FnShape, FromDictArray, FullyQualifiedUrl, FunctionType, GeneralDictionary, Get, HasUppercase, HybridFunction, IConfigurator, IFluentConfigurator, If, IfArray, IfBooleanLiteral, IfExtends, IfExtendsThen, IfFalse, IfLiteral, IfNumericLiteral, IfObject, IfOptionalLiteral, IfReadonlyArray, IfScalar, IfStartsWith, IfStringLiteral, IfTrue, IfUndefined, Include, Includes, IntersectingKeys, Ipv4, IsArray, IsBoolean, IsBooleanLiteral, IsCapitalized, IsFalse, IsFunction, IsLiteral, IsNull, IsNumber, IsNumericLiteral, IsObject, IsOptionalLiteral, IsReadonlyArray, IsScalar, IsStringLiteral, IsTrue, IsUndefined, KebabCase, KeyValue, KeyedRecord, Keys, KeysWithValue, KvFrom, KvTuple, LastInUnion, LeftWhitespace, Length, LogicFunction, LogicalCombinator, LowerAllCaps, LowerAlpha, ManyToMany, ManyToOne, ManyToZero, MapCard, MapCardinality, MapCardinalityFrom, MapCardinalityIllustrated, MapConfig, MapFn, MapFnInput, MapFnOutput, MapIR, MapInput, MapInputFrom, MapOR, MapOutput, MapOutputFrom, MapTo, Mapper, MapperApi, MaybeFalse, MaybeTrue, Mutable, MutableProps, NarrowBox, Narrowable, NarrowlyContains, NetworkProtocol, NonAlpha, NonNumericKeys, NonStringKeys, Not, NotEqual, NotFilter, Numeric, NumericFilter, NumericKeys, NumericString, ObjectType, OneToMany, OneToOne, OneToZero, Opaque, OpeningBracket, OptRequired, OptionalKeys, OptionalProps, Or, Parenthesis, PascalCase, Pluralize, PrivateKey, PrivateKeys, PublicKeys, Punctuation, PureFluentApi, RelativeUrl, Replace, RequireProps, RequiredKeys, RequiredProps, Retain, RightWhitespace, RuleDefinition, RuntimeProp, RuntimeType, SameKeys, SecondOfEach, SimpleFunction, SimplifyObject, SnakeCase, SpecialCharacters, Split, StartsWith, StringDelimiter, StringFilter, StringKeys, StringLength, Suggest, SuggestNumeric, ToFluent, Transformer, Trim, TrimLeft, TrimRight, TupleToUnion, Type, TypeApi, TypeDefault, TypeDefinition, TypeGuard, TypeOptions, Unbox, UndefinedArrayIsUnknown, UndefinedTreatment, UndefinedValue, UnionToIntersection, UnionToTuple, UniqueDictionary, UniqueForProp, Uniqueness, UnwrapNot, UpperAlpha, UrlBuilder, VariableName, Where, WhereNot, Whitespace, Widen, WithNumericKeys, WithStringKeys, WithValue, ZeroToMany, ZeroToOne, ZeroToZero, ZipCode, and, api, arrayToKeyLookup, arrayToObject, asArray, box, condition, createFnWithProps, defineProperties, defineType, dictArr, dictToKv, dictionaryTransform, entries, filter, filterDictArray, fnWithProps, groupBy, idLiteral, idTypeGuard, identity, ifArray, ifArrayPartial, ifBoolean, ifFalse, ifNull, ifNumber, ifString, ifTrue, ifUndefined, isArray, isBoolean, isBox, isFalse, isFunction, isNotFilter, isNull, isNumber, isNumericFilter, isObject, isString, isSymbol, isTrue, isType, isUndefined, keys, kindLiteral, kv, kvToDict, literal, mapTo, mapToDict, mapToFn, mapValues, nameLiteral, not, or, readonlyFnWithProps, ruleSet, strArrayToDict, type, typeApi, unbox, withValue };
|
|
2576
|
+
export { AfterFirst, AllCaps, Alpha, AlphaNumeric, AnyFunction, Api, ApiFunction, ApiValue, AppendToDictionary, AppendToObject, ArrConcat, Array$1 as Array, ArrayConverter, AsArray, AsFinalizedConfig, AssertExtends, Box, BoxValue, BoxedFnParams, BoxedReturn, Bracket, Break, CamelCase, CapitalizeWords, Cardinality, Cardinality0, Cardinality1, CardinalityExplicit, CardinalityFilter0, CardinalityFilter1, CardinalityIn, CardinalityInput, CardinalityNode, CardinalityOut, CardinalityTuple, ClosingBracket, Condition, ConditionFilter, Configurator, ConfiguredMap, Constructor, Contains, DEFAULT_MANY_TO_ONE_MAPPING, DEFAULT_ONE_TO_MANY_MAPPING, DEFAULT_ONE_TO_ONE_MAPPING, DashToSnake, DashUppercase, Dasherize, DecomposeMapConfig, DefaultManyToOneMapping, DefaultOneToManyMapping, DefaultOneToOneMapping, DefinePropertiesApi, DictArrApi, DictArray, DictArrayFilterCallback, DictArrayKv, DictChangeValue, DictFromKv, DictKvTuple, DictPartialApplication, DictPrependWithFn, DictReturnValues, DomainName, DynamicRule, DynamicRuleSet, Email, EndsWith, EnumValues, Equal, ExpandRecursively, ExpectExtends, ExplicitFunction, Extends, FilterContains, FilterDefn, FilterEnds, FilterEquals, FilterFn, FilterGreaterThan, FilterIs, FilterLessThan, FilterNotEqual, FilterStarts, FilterTuple, FinalReturn, FinalizedMapConfig, First, FirstKey, FirstKeyValue, FirstOfEach, FirstOrUndefined, FirstString, FluentConfigurator, FluentFunction, FnShape, FromDictArray, FullyQualifiedUrl, FunctionType, GeneralDictionary, Get, 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, 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, StripEnding, StripStarting, Suggest, SuggestNumeric, ToFluent, Transformer, Trim, TrimLeft, TrimRight, TupleToUnion, Type, TypeApi, TypeDefault, TypeDefinition, TypeGuard, TypeOptions, Unbox, UndefinedArrayIsUnknown, UndefinedTreatment, UndefinedValue, UnionToIntersection, UnionToTuple, UniqueDictionary, UniqueForProp, Uniqueness, UnwrapNot, UpperAlpha, UrlBuilder, VariableName, Where, WhereNot, Whitespace, Widen, WithNumericKeys, WithStringKeys, WithValue, ZeroToMany, ZeroToOne, ZeroToZero, ZipCode, and, api, arrayToKeyLookup, arrayToObject, asArray, box, condition, createFnWithProps, defineProperties, defineType, dictArr, dictToKv, dictionaryTransform, entries, filter, filterDictArray, fnWithProps, groupBy, idLiteral, idTypeGuard, identity, ifArray, ifArrayPartial, ifBoolean, ifFalse, ifNull, ifNumber, ifString, ifTrue, ifUndefined, isArray, isBoolean, isBox, isFalse, isFunction, isNotFilter, isNull, isNumber, isNumericFilter, isObject, isString, isSymbol, isTrue, isType, isUndefined, keys, kindLiteral, kv, kvToDict, literal, mapTo, mapToDict, mapToFn, mapValues, nameLiteral, not, or, readonlyFnWithProps, ruleSet, strArrayToDict, stripEnding, stripStarting, type, typeApi, unbox, withValue };
|
package/dist/index.js
CHANGED
|
@@ -87,6 +87,8 @@ __export(src_exports, {
|
|
|
87
87
|
readonlyFnWithProps: () => readonlyFnWithProps,
|
|
88
88
|
ruleSet: () => ruleSet,
|
|
89
89
|
strArrayToDict: () => strArrayToDict,
|
|
90
|
+
stripEnding: () => stripEnding,
|
|
91
|
+
stripStarting: () => stripStarting,
|
|
90
92
|
type: () => type,
|
|
91
93
|
typeApi: () => typeApi,
|
|
92
94
|
unbox: () => unbox,
|
|
@@ -776,6 +778,18 @@ function idTypeGuard(_o) {
|
|
|
776
778
|
function literal(obj) {
|
|
777
779
|
return obj;
|
|
778
780
|
}
|
|
781
|
+
|
|
782
|
+
// src/runtime/literals/stripEnding.ts
|
|
783
|
+
function stripEnding(content, strip) {
|
|
784
|
+
const re = new RegExp(`(.*)${strip}$`);
|
|
785
|
+
return content.endsWith(strip) ? content.replace(re, "$1") : content;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// src/runtime/literals/stripStarting.ts
|
|
789
|
+
function stripStarting(content, strip) {
|
|
790
|
+
const re = new RegExp(`^${strip}(.*)`);
|
|
791
|
+
return content.startsWith(strip) ? content.replace(re, "$1") : content;
|
|
792
|
+
}
|
|
779
793
|
// Annotate the CommonJS export names for ESM import in node:
|
|
780
794
|
0 && (module.exports = {
|
|
781
795
|
Configurator,
|
|
@@ -845,6 +859,8 @@ function literal(obj) {
|
|
|
845
859
|
readonlyFnWithProps,
|
|
846
860
|
ruleSet,
|
|
847
861
|
strArrayToDict,
|
|
862
|
+
stripEnding,
|
|
863
|
+
stripStarting,
|
|
848
864
|
type,
|
|
849
865
|
typeApi,
|
|
850
866
|
unbox,
|
package/dist/index.mjs
CHANGED
|
@@ -680,6 +680,18 @@ function idTypeGuard(_o) {
|
|
|
680
680
|
function literal(obj) {
|
|
681
681
|
return obj;
|
|
682
682
|
}
|
|
683
|
+
|
|
684
|
+
// src/runtime/literals/stripEnding.ts
|
|
685
|
+
function stripEnding(content, strip) {
|
|
686
|
+
const re = new RegExp(`(.*)${strip}$`);
|
|
687
|
+
return content.endsWith(strip) ? content.replace(re, "$1") : content;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// src/runtime/literals/stripStarting.ts
|
|
691
|
+
function stripStarting(content, strip) {
|
|
692
|
+
const re = new RegExp(`^${strip}(.*)`);
|
|
693
|
+
return content.startsWith(strip) ? content.replace(re, "$1") : content;
|
|
694
|
+
}
|
|
683
695
|
export {
|
|
684
696
|
Configurator,
|
|
685
697
|
DEFAULT_MANY_TO_ONE_MAPPING,
|
|
@@ -748,6 +760,8 @@ export {
|
|
|
748
760
|
readonlyFnWithProps,
|
|
749
761
|
ruleSet,
|
|
750
762
|
strArrayToDict,
|
|
763
|
+
stripEnding,
|
|
764
|
+
stripStarting,
|
|
751
765
|
type,
|
|
752
766
|
typeApi,
|
|
753
767
|
unbox,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inferred-types",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"description": "Functions which provide useful type inference on TS projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ken Snyder<ken@ken.net>",
|
|
@@ -32,16 +32,16 @@
|
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@type-challenges/utils": "~0.1.1",
|
|
35
|
-
"@types/node": "^16.18.
|
|
36
|
-
"@typescript-eslint/eslint-plugin": "^5.45.
|
|
37
|
-
"@typescript-eslint/parser": "^5.45.
|
|
38
|
-
"@vitest/ui": "^0.25.
|
|
35
|
+
"@types/node": "^16.18.4",
|
|
36
|
+
"@typescript-eslint/eslint-plugin": "^5.45.1",
|
|
37
|
+
"@typescript-eslint/parser": "^5.45.1",
|
|
38
|
+
"@vitest/ui": "^0.25.4",
|
|
39
39
|
"bumpp": "^8.2.1",
|
|
40
40
|
"common-types": "^1.33.2",
|
|
41
41
|
"cross-env": "^7.0.3",
|
|
42
42
|
"dd": "^0.25.4",
|
|
43
43
|
"dotenv": "^16.0.3",
|
|
44
|
-
"eslint": "^8.
|
|
44
|
+
"eslint": "^8.29.0",
|
|
45
45
|
"eslint-config-prettier": "^8.5.0",
|
|
46
46
|
"eslint-plugin-import": "^2.26.0",
|
|
47
47
|
"eslint-plugin-prettier": "^4.2.1",
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
"sharp": "^0.31.2",
|
|
54
54
|
"tsup": "^6.5.0",
|
|
55
55
|
"typescript": "^4.9.3",
|
|
56
|
-
"vite": "^3.2.
|
|
57
|
-
"vitest": "^0.25.
|
|
56
|
+
"vite": "^3.2.5",
|
|
57
|
+
"vitest": "^0.25.4"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"brilliant-errors": "^0.6.1"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { PathJoin } from "src/types/alphabetic/PathJoin";
|
|
2
|
+
import { stripStarting } from "./stripStarting";
|
|
3
|
+
import { stripEnding } from "./stripEnding";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* **pathJoin**`<T,U>()`
|
|
7
|
+
*
|
|
8
|
+
* Run time utility which joins two strings together with
|
|
9
|
+
* the intent to have them be divided by a Posix `/` character
|
|
10
|
+
* appropriate for Unix file paths and URLs.
|
|
11
|
+
*/
|
|
12
|
+
export function pathJoin<T extends string, U extends string>(begin: T, finish: U): PathJoin<T, U> {
|
|
13
|
+
const start = stripEnding(begin, "/");
|
|
14
|
+
const end = stripStarting(finish, "/");
|
|
15
|
+
|
|
16
|
+
return `${start}/${end}` as PathJoin<T, U>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { StripEnding } from "src/types/alphabetic/StripEnding";
|
|
2
|
+
|
|
3
|
+
export function stripEnding<T extends string, U extends string>(
|
|
4
|
+
content: T,
|
|
5
|
+
strip: U
|
|
6
|
+
): StripEnding<T, U> {
|
|
7
|
+
const re = new RegExp(`(.*)${strip}$`);
|
|
8
|
+
return (content.endsWith(strip) ? content.replace(re, "$1") : content) as StripEnding<T, U>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { StripStarting } from "src/types/alphabetic/StripStarting";
|
|
2
|
+
|
|
3
|
+
export function stripStarting<T extends string, U extends string>(
|
|
4
|
+
content: T,
|
|
5
|
+
strip: U
|
|
6
|
+
): StripStarting<T, U> {
|
|
7
|
+
const re = new RegExp(`^${strip}(.*)`);
|
|
8
|
+
return (
|
|
9
|
+
content.startsWith(strip)
|
|
10
|
+
? // starts with
|
|
11
|
+
content.replace(re, "$1")
|
|
12
|
+
: // does not
|
|
13
|
+
content
|
|
14
|
+
) as StripStarting<T, U>;
|
|
15
|
+
}
|
|
@@ -20,7 +20,7 @@ export function isFalse<T>(i: T) {
|
|
|
20
20
|
* typed so unlike the type utility there is no "MAYBE" state but if a wide type if
|
|
21
21
|
* encountered the _type_ will the union of `IF` and `ELSE`.
|
|
22
22
|
*/
|
|
23
|
-
export function ifFalse<T extends
|
|
23
|
+
export function ifFalse<T extends boolean, IF extends Narrowable, ELSE extends Narrowable>(
|
|
24
24
|
val: T,
|
|
25
25
|
ifVal: IF,
|
|
26
26
|
elseVal: ELSE
|
|
@@ -12,8 +12,7 @@ export function isTrue<T extends Narrowable>(i: T) {
|
|
|
12
12
|
* **ifTrue**
|
|
13
13
|
*
|
|
14
14
|
* Strongly type-aware conditional statement which checks whether a value is
|
|
15
|
-
*
|
|
16
|
-
* of this criteria.
|
|
15
|
+
* _true_.
|
|
17
16
|
*
|
|
18
17
|
* @param val the value being tested
|
|
19
18
|
* @param ifVal the value (strongly typed) returned if val is _true_ value
|
|
@@ -23,7 +22,7 @@ export function isTrue<T extends Narrowable>(i: T) {
|
|
|
23
22
|
* typed so unlike the type utility there is no "MAYBE" state but if a wide type if
|
|
24
23
|
* encountered the _type_ will the union of `IF` and `ELSE`.
|
|
25
24
|
*/
|
|
26
|
-
export function ifTrue<T extends
|
|
25
|
+
export function ifTrue<T extends boolean, IF extends Narrowable, ELSE extends Narrowable>(
|
|
27
26
|
val: T,
|
|
28
27
|
ifVal: IF,
|
|
29
28
|
elseVal: ELSE
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Narrowable } from "src/types";
|
|
1
2
|
import { IfStartsWith, StartsWith } from "src/types/boolean-logic";
|
|
2
3
|
import { IfUndefined } from "src/types/boolean-logic/IsUndefined";
|
|
3
4
|
import { createFnWithProps } from "../createFnWithProps";
|
|
@@ -88,22 +89,19 @@ export type StringLiteralFn<S extends string = string> = <T extends S>(input: T)
|
|
|
88
89
|
* returns is able to
|
|
89
90
|
*/
|
|
90
91
|
export const ifStartsWith =
|
|
91
|
-
<
|
|
92
|
-
TStartsWith extends string,
|
|
93
|
-
TIf extends <T extends string>(input: T) => any,
|
|
94
|
-
TElse extends <T extends string>(input: T) => any
|
|
95
|
-
>(
|
|
92
|
+
<TStartsWith extends string, TIf extends Narrowable, TElse extends Narrowable>(
|
|
96
93
|
/** the string literal _start value_ which a string must begin with */
|
|
97
94
|
start: TStartsWith,
|
|
98
95
|
/** a mutation function when a value _does_ start with `TStartsWith` */
|
|
99
|
-
isTrue: TIf,
|
|
96
|
+
isTrue: <T extends string>(input: T) => TIf,
|
|
100
97
|
/** an optional mutation function */
|
|
101
|
-
isFalse: TElse
|
|
98
|
+
isFalse: <T extends string>(input: T) => TElse
|
|
102
99
|
) =>
|
|
103
|
-
<
|
|
100
|
+
<TTextValue extends string>(input: TTextValue) =>
|
|
104
101
|
ifTrue(
|
|
105
102
|
// condition
|
|
106
103
|
startsWith(start)(input),
|
|
104
|
+
// handlers
|
|
107
105
|
isTrue(input),
|
|
108
106
|
isFalse(input)
|
|
109
|
-
)
|
|
107
|
+
);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { IfLiteral } from "../boolean-logic";
|
|
2
|
+
import { StripEnding } from "./StripEnding";
|
|
3
|
+
import { StripStarting } from "./StripStarting";
|
|
4
|
+
/**
|
|
5
|
+
* **PathJoin**`<T,U>`
|
|
6
|
+
*
|
|
7
|
+
* Type utility which joins two strings together with the
|
|
8
|
+
* goal of making it a valid file or URI path (based on the
|
|
9
|
+
* Posix standard for file paths).
|
|
10
|
+
*
|
|
11
|
+
* Primarily, this means that it ensures that both `T` and `U`
|
|
12
|
+
* are separated by a single `/` character. Of course if either
|
|
13
|
+
* `T` or `U` are _wide_ string types then the resulting type
|
|
14
|
+
* will be more limited.
|
|
15
|
+
*
|
|
16
|
+
* **Note:** that in the case that both `T` and `U` are wide,
|
|
17
|
+
* we opt to type the result as just a _string_ rather than
|
|
18
|
+
* `${string}/${string}` which might be more precise 99% of
|
|
19
|
+
* the time but where `T` is an empty string there actually
|
|
20
|
+
* is no guarantee of a `/` character. Similarly we must
|
|
21
|
+
* type the case where `U` is narrow but `T` is wide as
|
|
22
|
+
* being `${string}${U}` instead of `${string}/${U}`.
|
|
23
|
+
*/
|
|
24
|
+
export type PathJoin<
|
|
25
|
+
// leading string
|
|
26
|
+
T extends string,
|
|
27
|
+
// trailing string
|
|
28
|
+
U extends string
|
|
29
|
+
> = IfLiteral<
|
|
30
|
+
T,
|
|
31
|
+
// Literal T guaranteed
|
|
32
|
+
IfLiteral<
|
|
33
|
+
// conditional
|
|
34
|
+
U,
|
|
35
|
+
`${StripEnding<T, "/">}/${StripStarting<U, "/">}`,
|
|
36
|
+
`${StripEnding<T, "/">}/${string}`
|
|
37
|
+
>,
|
|
38
|
+
// wide `T` encountered
|
|
39
|
+
IfLiteral<U, `${string}${U}`, string>
|
|
40
|
+
>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { IfLiteral } from "../boolean-logic/IsLiteral";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* **StripEnding**`<T, U>`
|
|
5
|
+
*
|
|
6
|
+
* Will strip off of `T` the ending defined by `U` when
|
|
7
|
+
* both are string literals.
|
|
8
|
+
* ```ts
|
|
9
|
+
* type T = "Hello World";
|
|
10
|
+
* type U = " World";
|
|
11
|
+
* // "Hello"
|
|
12
|
+
* type R = StripEnding<T,U>;
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export type StripEnding<T extends string, U extends string> = IfLiteral<
|
|
16
|
+
// can only operate on literal strings
|
|
17
|
+
T,
|
|
18
|
+
// this path represents successful strip opp
|
|
19
|
+
// but we must never accept `U` being wide
|
|
20
|
+
string extends U ? never : T extends `${infer Before}${U}` ? Before : T,
|
|
21
|
+
// here we must stay wide
|
|
22
|
+
string
|
|
23
|
+
>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { IfLiteral } from "../boolean-logic/IsLiteral";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* **StripStarting**`<T, U>`
|
|
5
|
+
*
|
|
6
|
+
* Will strip off of `T` the starting string defined by `U` when
|
|
7
|
+
* both are string literals.
|
|
8
|
+
* ```ts
|
|
9
|
+
* type T = "Hello World";
|
|
10
|
+
* type U = "Hello ";
|
|
11
|
+
* // "World"
|
|
12
|
+
* type R = StripStarting<T,U>;
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export type StripStarting<T extends string, U extends string> = IfLiteral<
|
|
16
|
+
// can only operate on literal strings
|
|
17
|
+
T,
|
|
18
|
+
// this path represents successful strip opp
|
|
19
|
+
// but we must never accept `U` being wide
|
|
20
|
+
string extends U ? never : T extends `${U}${infer After}` ? After : T,
|
|
21
|
+
// here we must stay wide
|
|
22
|
+
string
|
|
23
|
+
>;
|
|
@@ -18,6 +18,8 @@ export * from "./LowerAllCaps";
|
|
|
18
18
|
export * from "./PascalCase";
|
|
19
19
|
export * from "./Pluralize";
|
|
20
20
|
export * from "./SnakeCase";
|
|
21
|
+
export * from "./StripStarting";
|
|
22
|
+
export * from "./StripEnding";
|
|
21
23
|
export * from "./alpha-characters";
|
|
22
24
|
export * from "./Url";
|
|
23
25
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IsStringLiteral } from "src/types/boolean-logic";
|
|
2
|
+
import { Narrowable } from "../Narrowable";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* **EndsWith**<T,U>
|
|
@@ -9,14 +10,31 @@ import { IfStringLiteral } from "src/types/boolean-logic";
|
|
|
9
10
|
* to a literal `true` or `false` but if either is not a literal that it will
|
|
10
11
|
* just resolve to `boolean` as the value can not be known at design time..
|
|
11
12
|
*/
|
|
12
|
-
export type EndsWith<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
export type EndsWith<
|
|
14
|
+
TValue extends string,
|
|
15
|
+
TEndsWith extends string
|
|
16
|
+
> = IsStringLiteral<TEndsWith> extends true
|
|
17
|
+
? IsStringLiteral<TValue> extends true // both literals
|
|
18
|
+
? TValue extends `${string}${TEndsWith}`
|
|
19
|
+
? true
|
|
20
|
+
: false
|
|
21
|
+
: boolean
|
|
22
|
+
: boolean;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* **IfEndsWith**<TValue, TEndsWith, IF, ELSE, MAYBE>
|
|
26
|
+
*
|
|
27
|
+
* Type utility which converts type to `IF` type _if_ `TValue` _ends with_ `TEndsWith` but
|
|
28
|
+
* otherwise converts type to `ELSE`. If there are wide types in the mix then the type will
|
|
29
|
+
* result in the union of IF and ELSE.
|
|
30
|
+
*/
|
|
31
|
+
export type IfEndsWith<
|
|
32
|
+
TValue extends string,
|
|
33
|
+
TEndsWith extends string,
|
|
34
|
+
IF extends Narrowable,
|
|
35
|
+
ELSE extends Narrowable
|
|
36
|
+
> = EndsWith<TValue, TEndsWith> extends true
|
|
37
|
+
? IF
|
|
38
|
+
: EndsWith<TValue, TEndsWith> extends false
|
|
39
|
+
? ELSE
|
|
40
|
+
: IF | ELSE;
|
|
@@ -1,13 +1,22 @@
|
|
|
1
|
+
import { Narrowable } from "../Narrowable";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* **Extends**`<T, EXTENDS>`
|
|
3
5
|
*
|
|
4
6
|
* Boolean type utility which returns `true` if `T` _extends_ `EXTENDS`.
|
|
5
7
|
*/
|
|
6
|
-
export type Extends<T, EXTENDS> = T extends EXTENDS
|
|
8
|
+
export type Extends<T extends Narrowable, EXTENDS extends Narrowable> = T extends EXTENDS
|
|
9
|
+
? true
|
|
10
|
+
: false;
|
|
7
11
|
/**
|
|
8
12
|
* **IfExtends**
|
|
9
13
|
*
|
|
10
14
|
* Branching type utility which returns type `IF` when `E` _extends_ `T`; otherwise
|
|
11
15
|
* it will return the type `ELSE`.
|
|
12
16
|
*/
|
|
13
|
-
export type IfExtends<
|
|
17
|
+
export type IfExtends<
|
|
18
|
+
T extends Narrowable,
|
|
19
|
+
EXTENDS extends Narrowable,
|
|
20
|
+
IF extends Narrowable,
|
|
21
|
+
ELSE extends Narrowable
|
|
22
|
+
> = Extends<T, EXTENDS> extends true ? IF : ELSE;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { TupleToUnion } from "../type-conversion";
|
|
2
|
-
import { IsLiteral } from "./IsLiteral";
|
|
3
|
-
import { IsStringLiteral } from "./IsStringLiteral";
|
|
2
|
+
import { IsLiteral, IsStringLiteral } from "./IsLiteral";
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
|
-
* **Includes
|
|
5
|
+
* **Includes**`<TSource, TValue>`
|
|
7
6
|
*
|
|
8
7
|
* Type utility which returns `true` or `false` based on whether `TValue` is found
|
|
9
8
|
* in `TSource`. Where `TSource` can be a string literal or an array of string literals.
|
|
@@ -13,7 +12,7 @@ import { IsStringLiteral } from "./IsStringLiteral";
|
|
|
13
12
|
* a type of `boolean`.
|
|
14
13
|
*/
|
|
15
14
|
export type Includes<
|
|
16
|
-
TSource extends string | string[],
|
|
15
|
+
TSource extends string | readonly string[],
|
|
17
16
|
TValue extends string
|
|
18
17
|
> = TSource extends string[]
|
|
19
18
|
? IsStringLiteral<TupleToUnion<TSource>> extends true
|
|
@@ -1,6 +1,47 @@
|
|
|
1
|
+
import { Narrowable } from "../Narrowable";
|
|
1
2
|
import { IsBooleanLiteral } from "./boolean";
|
|
2
|
-
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* **IsStringLiteral**
|
|
6
|
+
*
|
|
7
|
+
* Type utility which returns true/false if the string a _string literal_ versus
|
|
8
|
+
* just the _string_ type.
|
|
9
|
+
*/
|
|
10
|
+
export type IsStringLiteral<T extends Narrowable> = [T] extends [string]
|
|
11
|
+
? string extends T
|
|
12
|
+
? false
|
|
13
|
+
: true
|
|
14
|
+
: false;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* **IfStringLiteral**
|
|
18
|
+
*
|
|
19
|
+
* Branch utility which returns `IF` type when `T` is a string literal and `ELSE` otherwise
|
|
20
|
+
*/
|
|
21
|
+
export type IfStringLiteral<T extends string, IF extends Narrowable, ELSE extends Narrowable> = [
|
|
22
|
+
IsStringLiteral<T>
|
|
23
|
+
] extends [true]
|
|
24
|
+
? IF
|
|
25
|
+
: ELSE;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* **IsNumericLiteral**
|
|
29
|
+
*
|
|
30
|
+
* Type utility which returns true/false if the numeric value a _numeric literal_ versus
|
|
31
|
+
* just the _number_ type.
|
|
32
|
+
*/
|
|
33
|
+
export type IsNumericLiteral<T extends number> = number extends T ? false : true;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* **IfNumericLiteral**
|
|
37
|
+
*
|
|
38
|
+
* Branch utility which returns `IF` type when `T` is a numeric literal and `ELSE` otherwise
|
|
39
|
+
*/
|
|
40
|
+
export type IfNumericLiteral<
|
|
41
|
+
T extends number,
|
|
42
|
+
IF extends Narrowable,
|
|
43
|
+
ELSE extends Narrowable
|
|
44
|
+
> = IsNumericLiteral<T> extends true ? IF : ELSE;
|
|
4
45
|
|
|
5
46
|
// [note on handling of boolean](https://stackoverflow.com/questions/74213646/detecting-type-literals-works-in-isolation-but-not-when-combined-with-other-lite/74213713#74213713)
|
|
6
47
|
|
|
@@ -43,7 +84,9 @@ export type IsOptionalLiteral<T> = [Exclude<T, undefined>] extends [string]
|
|
|
43
84
|
*
|
|
44
85
|
* Branch type utility with return `IF` when `T` is a _literal_ value and `ELSE` otherwise
|
|
45
86
|
*/
|
|
46
|
-
export type IfLiteral<T, IF, ELSE> = IsLiteral<T> extends true
|
|
87
|
+
export type IfLiteral<T, IF extends Narrowable, ELSE extends Narrowable> = IsLiteral<T> extends true
|
|
88
|
+
? IF
|
|
89
|
+
: ELSE;
|
|
47
90
|
|
|
48
91
|
/**
|
|
49
92
|
* **IfOptionalLiteral**
|
|
@@ -51,4 +94,8 @@ export type IfLiteral<T, IF, ELSE> = IsLiteral<T> extends true ? IF : ELSE;
|
|
|
51
94
|
* Branch type utility with return `IF` when `T` is a _literal_ value (with possibly
|
|
52
95
|
* the inclusion of _undefined_); otherwise returns the type `ELSE`
|
|
53
96
|
*/
|
|
54
|
-
export type IfOptionalLiteral<
|
|
97
|
+
export type IfOptionalLiteral<
|
|
98
|
+
T,
|
|
99
|
+
IF extends Narrowable,
|
|
100
|
+
ELSE extends Narrowable
|
|
101
|
+
> = IsOptionalLiteral<T> extends true ? IF : ELSE;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { Narrowable } from "../Narrowable";
|
|
2
|
+
|
|
3
|
+
export type IsScalar<T extends Narrowable> = [T] extends [string]
|
|
2
4
|
? true
|
|
3
5
|
: [T] extends [number]
|
|
4
6
|
? true
|
|
@@ -7,8 +9,12 @@ export type IsScalar<T> = [T] extends [string]
|
|
|
7
9
|
: false;
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
|
-
* **IfScalar
|
|
12
|
+
* **IfScalar**`<T, IF, ELSE>`
|
|
11
13
|
*
|
|
12
|
-
* Branch type utility which returns `IF` when `T` is a scalar value and `ELSE` otherwise
|
|
14
|
+
* Branch type utility which returns `IF` when `T` is a scalar value (aka, string, number, or boolean) and `ELSE` otherwise
|
|
13
15
|
*/
|
|
14
|
-
export type IfScalar<
|
|
16
|
+
export type IfScalar<
|
|
17
|
+
T extends Narrowable,
|
|
18
|
+
IF extends Narrowable,
|
|
19
|
+
ELSE extends Narrowable
|
|
20
|
+
> = IsScalar<T> extends true ? IF : ELSE;
|
|
@@ -13,4 +13,8 @@ export type IsUndefined<T extends Narrowable> = T extends undefined ? true : fal
|
|
|
13
13
|
* Type utility which returns `IF` type when `T` is an _undefined_
|
|
14
14
|
* otherwise returns `ELSE` type.
|
|
15
15
|
*/
|
|
16
|
-
export type IfUndefined<
|
|
16
|
+
export type IfUndefined<
|
|
17
|
+
T,
|
|
18
|
+
IF extends Narrowable,
|
|
19
|
+
ELSE extends Narrowable
|
|
20
|
+
> = IsUndefined<T> extends true ? IF : ELSE;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IsStringLiteral } from "src/types/boolean-logic";
|
|
2
2
|
import { Narrowable } from "../Narrowable";
|
|
3
3
|
/**
|
|
4
4
|
* **StartsWith**<TValue, TStartsWith>
|
|
@@ -9,17 +9,16 @@ import { Narrowable } from "../Narrowable";
|
|
|
9
9
|
* to a literal `true` or `false` but if either is not a literal that it will
|
|
10
10
|
* just resolve to `boolean` as the value can not be known at design time..
|
|
11
11
|
*/
|
|
12
|
-
export type StartsWith<
|
|
13
|
-
|
|
12
|
+
export type StartsWith<
|
|
13
|
+
TValue extends string,
|
|
14
|
+
TStartsWith extends string
|
|
15
|
+
> = IsStringLiteral<TStartsWith> extends true
|
|
16
|
+
? IsStringLiteral<TValue> extends true // both literals
|
|
14
17
|
? TValue extends `${TStartsWith}${string}`
|
|
15
|
-
?
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
>
|
|
20
|
-
: IfStringLiteral<TValue, false, boolean>
|
|
21
|
-
: false
|
|
22
|
-
: false;
|
|
18
|
+
? true
|
|
19
|
+
: false
|
|
20
|
+
: boolean
|
|
21
|
+
: boolean;
|
|
23
22
|
|
|
24
23
|
/**
|
|
25
24
|
* **IfStartsWith**<TValue, TStartsWith, IF, ELSE, MAYBE>
|
|
@@ -32,8 +31,8 @@ export type StartsWith<TValue extends unknown, TStartsWith extends unknown> = TV
|
|
|
32
31
|
* type and therefore the type is unknown at design time.
|
|
33
32
|
*/
|
|
34
33
|
export type IfStartsWith<
|
|
35
|
-
TValue extends
|
|
36
|
-
TStartsWith extends
|
|
34
|
+
TValue extends string,
|
|
35
|
+
TStartsWith extends string,
|
|
37
36
|
IF extends Narrowable,
|
|
38
37
|
ELSE extends Narrowable
|
|
39
38
|
> = StartsWith<TValue, TStartsWith> extends true
|
|
@@ -41,22 +41,24 @@ export type IsFalse<T extends Narrowable> = IsBoolean<T> extends true
|
|
|
41
41
|
* to the IF, ELSE, or MAYBE generic types passed in where _maybe_ is when T
|
|
42
42
|
* is the wide type of `boolean`
|
|
43
43
|
*/
|
|
44
|
-
export type IfTrue<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
export type IfTrue<
|
|
45
|
+
T extends boolean,
|
|
46
|
+
IF extends Narrowable,
|
|
47
|
+
ELSE extends Narrowable,
|
|
48
|
+
MAYBE extends Narrowable
|
|
49
|
+
> = IsTrue<T> extends true ? IF : IsTrue<T> extends false ? ELSE : MAYBE;
|
|
49
50
|
|
|
50
51
|
/**
|
|
51
52
|
* Type utility which checks for literal `false` value and then switches type
|
|
52
53
|
* to the IF, ELSE, or MAYBE generic types passed in where _maybe_ is when T
|
|
53
54
|
* is the wide type of `boolean`
|
|
54
55
|
*/
|
|
55
|
-
export type IfFalse<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
export type IfFalse<
|
|
57
|
+
T extends Narrowable,
|
|
58
|
+
IF extends Narrowable,
|
|
59
|
+
ELSE extends Narrowable,
|
|
60
|
+
MAYBE extends Narrowable
|
|
61
|
+
> = IsFalse<T> extends true ? IF : IsTrue<T> extends false ? ELSE : MAYBE;
|
|
60
62
|
|
|
61
63
|
/**
|
|
62
64
|
* **IsBooleanLiteral**
|
|
@@ -64,13 +66,19 @@ export type IfFalse<T, IF, ELSE, MAYBE> = IsFalse<T> extends true
|
|
|
64
66
|
* Type utility which returns true/false if the boolean value is a _boolean literal_ versus
|
|
65
67
|
* just the wider _boolean_ type.
|
|
66
68
|
*/
|
|
67
|
-
export type IsBooleanLiteral<T extends
|
|
69
|
+
export type IsBooleanLiteral<T extends Narrowable> = IsTrue<T> extends true
|
|
70
|
+
? true
|
|
71
|
+
: IsFalse<T> extends true
|
|
72
|
+
? true
|
|
73
|
+
: false;
|
|
68
74
|
|
|
69
75
|
/**
|
|
70
76
|
* **IfBooleanLiteral**
|
|
71
77
|
*
|
|
72
78
|
* Branch utility which returns `IF` type when `T` is a boolean literal and `ELSE` otherwise
|
|
73
79
|
*/
|
|
74
|
-
export type IfBooleanLiteral<
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
export type IfBooleanLiteral<
|
|
81
|
+
T extends boolean,
|
|
82
|
+
IF extends Narrowable,
|
|
83
|
+
ELSE extends Narrowable
|
|
84
|
+
> = IsBooleanLiteral<T> extends true ? IF : ELSE;
|
|
File without changes
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
export * from "./array";
|
|
2
2
|
export * from "./Includes";
|
|
3
3
|
export * from "./boolean";
|
|
4
|
-
export * from "./IsNumericLiteral";
|
|
5
4
|
export * from "./IsScalar";
|
|
6
|
-
export * from "./IsStringLiteral";
|
|
7
5
|
export * from "./IsLiteral";
|
|
8
6
|
export * from "./IsUndefined";
|
|
9
7
|
export * from "./Extends";
|
|
@@ -11,3 +9,5 @@ export * from "./TypeDefault";
|
|
|
11
9
|
export * from "./object";
|
|
12
10
|
export * from "./StartsWith";
|
|
13
11
|
export * from "./EndsWith";
|
|
12
|
+
export * from "./Or";
|
|
13
|
+
export * from "./equivalency";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FunctionType } from "../FunctionType";
|
|
2
2
|
import { Mutable } from "../Mutable";
|
|
3
|
+
import { Narrowable } from "../Narrowable";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* **IsObject**
|
|
@@ -24,4 +25,6 @@ export type IsObject<T> = Mutable<T> extends Record<string, any>
|
|
|
24
25
|
* Branch type utility with return `IF` when `T` extends an object type
|
|
25
26
|
* and `ELSE` otherwise
|
|
26
27
|
*/
|
|
27
|
-
export type IfObject<T, IF, ELSE> = IsObject<T> extends true
|
|
28
|
+
export type IfObject<T, IF extends Narrowable, ELSE extends Narrowable> = IsObject<T> extends true
|
|
29
|
+
? IF
|
|
30
|
+
: ELSE;
|
package/src/types/index.ts
CHANGED
|
@@ -37,7 +37,6 @@ export * from "./fluent/index";
|
|
|
37
37
|
export * from "./functions/index";
|
|
38
38
|
export * from "./kv/index";
|
|
39
39
|
export * from "./lists/index";
|
|
40
|
-
export * from "./combinators/index";
|
|
41
40
|
export * from "./literal-unions/index";
|
|
42
41
|
export * from "./string-literals/index";
|
|
43
42
|
export * from "./tuples/index";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **FilterTuple**
|
|
3
|
+
*
|
|
4
|
+
* Allows a known tuple `T` to be _filtered down_ by eliminating all items
|
|
5
|
+
* in the Tuple that _extend_ type `F`
|
|
6
|
+
* ```ts
|
|
7
|
+
* type T = [1,"foo",3];
|
|
8
|
+
* // [1,3]
|
|
9
|
+
* type T2 = FilterTuple<T, string>;
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export type FilterTuple<
|
|
13
|
+
TTuple extends any[] | readonly any[],
|
|
14
|
+
TFilter,
|
|
15
|
+
Result extends any[] = []
|
|
16
|
+
> = TTuple extends [infer A, ...infer R]
|
|
17
|
+
? [A] extends [TFilter]
|
|
18
|
+
? FilterTuple<R, TFilter, Result>
|
|
19
|
+
: FilterTuple<R, TFilter, [...Result, A]>
|
|
20
|
+
: Result;
|
package/src/types/lists/index.ts
CHANGED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Equal, Expect } from "@type-challenges/utils";
|
|
2
|
+
import { pathJoin } from "src/runtime/literals/pathJoin";
|
|
3
|
+
import { PathJoin } from "src/types/alphabetic/PathJoin";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
|
|
6
|
+
// Note: type tests fail visible inspection but pass from Vitest
|
|
7
|
+
// standpoint so always be sure to run `tsc --noEmit` over your test files to
|
|
8
|
+
// gain validation that no new type vulnerabilities have cropped up.
|
|
9
|
+
|
|
10
|
+
describe("PathJoin<T,U>", () => {
|
|
11
|
+
it("only literals / happy path", () => {
|
|
12
|
+
type T1 = PathJoin<"foo", "bar">;
|
|
13
|
+
type T2 = PathJoin<"foo/", "bar">;
|
|
14
|
+
type T3 = PathJoin<"foo", "/bar">;
|
|
15
|
+
type T4 = PathJoin<"foo/", "/bar">;
|
|
16
|
+
|
|
17
|
+
type cases = [
|
|
18
|
+
// neither have divider
|
|
19
|
+
Expect<Equal<T1, "foo/bar">>,
|
|
20
|
+
// one has, one does not
|
|
21
|
+
Expect<Equal<T2, "foo/bar">>,
|
|
22
|
+
Expect<Equal<T3, "foo/bar">>,
|
|
23
|
+
// both have
|
|
24
|
+
Expect<Equal<T4, "foo/bar">>
|
|
25
|
+
];
|
|
26
|
+
const cases: cases = [true, true, true, true];
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("wide types mixed in", () => {
|
|
30
|
+
type T1 = PathJoin<"foo", string>;
|
|
31
|
+
type T2 = PathJoin<"foo/", string>;
|
|
32
|
+
type T3 = PathJoin<string, "/bar">;
|
|
33
|
+
type T4 = PathJoin<string, "bar">;
|
|
34
|
+
|
|
35
|
+
type cases = [
|
|
36
|
+
Expect<Equal<T1, `foo/${string}`>>,
|
|
37
|
+
Expect<Equal<T2, `foo/${string}`>>,
|
|
38
|
+
Expect<Equal<T3, `${string}/bar`>>,
|
|
39
|
+
Expect<Equal<T4, `${string}bar`>>
|
|
40
|
+
];
|
|
41
|
+
const cases: cases = [true, true, true, true];
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe("pathJoin() runtime util", () => {
|
|
46
|
+
it("happy path", () => {
|
|
47
|
+
const t1 = pathJoin("foo", "bar" as string);
|
|
48
|
+
const t2 = pathJoin("foo/", "bar" as string);
|
|
49
|
+
const t3 = pathJoin("foo" as string, "/bar");
|
|
50
|
+
const t4 = pathJoin("foo/" as string, "/bar");
|
|
51
|
+
const t5 = pathJoin("foo/" as string, "bar");
|
|
52
|
+
|
|
53
|
+
// runtime tests
|
|
54
|
+
[t1, t2, t3, t4].forEach((test) => expect(test).toBe("foo/bar"));
|
|
55
|
+
|
|
56
|
+
// type tests
|
|
57
|
+
type cases = [
|
|
58
|
+
Expect<Equal<typeof t1, `foo/${string}`>>,
|
|
59
|
+
Expect<Equal<typeof t2, `foo/${string}`>>,
|
|
60
|
+
Expect<Equal<typeof t3, `${string}/bar`>>,
|
|
61
|
+
Expect<Equal<typeof t4, `${string}/bar`>>,
|
|
62
|
+
Expect<Equal<typeof t5, `${string}bar`>>
|
|
63
|
+
];
|
|
64
|
+
const cases: cases = [true, true, true, true, true];
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("with wide types", () => {
|
|
68
|
+
const t1 = pathJoin("foo", "bar");
|
|
69
|
+
const t2 = pathJoin("foo/", "bar");
|
|
70
|
+
const t3 = pathJoin("foo", "/bar");
|
|
71
|
+
const t4 = pathJoin("foo/", "/bar");
|
|
72
|
+
// runtime tests
|
|
73
|
+
[t1, t2, t3, t4].forEach((test) => expect(test, "runtime failure").toBe("foo/bar"));
|
|
74
|
+
|
|
75
|
+
// type tests
|
|
76
|
+
type cases = [
|
|
77
|
+
// neither have divider
|
|
78
|
+
Expect<Equal<typeof t1, "foo/bar">>,
|
|
79
|
+
// one has, one does not
|
|
80
|
+
Expect<Equal<typeof t2, "foo/bar">>,
|
|
81
|
+
Expect<Equal<typeof t3, "foo/bar">>,
|
|
82
|
+
// both have
|
|
83
|
+
Expect<Equal<typeof t4, "foo/bar">>
|
|
84
|
+
];
|
|
85
|
+
const cases: cases = [true, true, true, true];
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
ifUndefined,
|
|
12
12
|
isTrue,
|
|
13
13
|
} from "src/runtime/type-checks";
|
|
14
|
-
import { EndsWith, Extends, Or, StartsWith } from "src/types";
|
|
14
|
+
import { EndsWith, Extends, LowerAlpha, Or, StartsWith } from "src/types";
|
|
15
15
|
import { ifStartsWith, startsWith } from "src/runtime/type-checks/startsWith";
|
|
16
16
|
import { box } from "src/runtime/literals";
|
|
17
17
|
import { or } from "src/runtime";
|
|
@@ -236,14 +236,21 @@ describe("runtime if/is", () => {
|
|
|
236
236
|
type T4 = StartsWith<string, "foo">;
|
|
237
237
|
type T5 = StartsWith<string, string>;
|
|
238
238
|
|
|
239
|
+
type T6 = StartsWith<"alpha", LowerAlpha>;
|
|
240
|
+
type T7 = StartsWith<"Alpha", LowerAlpha>;
|
|
241
|
+
|
|
239
242
|
type cases = [
|
|
240
243
|
Expect<Equal<T1, true>>, //
|
|
241
244
|
Expect<Equal<T2, false>>,
|
|
245
|
+
// if either the "start with" or "val" props are wide then we can't resolve at design time
|
|
242
246
|
Expect<Equal<T3, boolean>>,
|
|
243
247
|
Expect<Equal<T4, boolean>>,
|
|
244
|
-
Expect<Equal<T5, boolean
|
|
248
|
+
Expect<Equal<T5, boolean>>,
|
|
249
|
+
// LowerAlpha is a string literal
|
|
250
|
+
Expect<Equal<T6, true>>,
|
|
251
|
+
Expect<Equal<T7, false>>
|
|
245
252
|
];
|
|
246
|
-
const cases: cases = [true, true, true, true, true];
|
|
253
|
+
const cases: cases = [true, true, true, true, true, true, true];
|
|
247
254
|
});
|
|
248
255
|
|
|
249
256
|
it("EndsWith<T,U>", () => {
|
|
@@ -288,7 +295,7 @@ describe("runtime if/is", () => {
|
|
|
288
295
|
// condition
|
|
289
296
|
"foo",
|
|
290
297
|
// inline
|
|
291
|
-
(i) => `welcome ${i}
|
|
298
|
+
(i) => `welcome ${i}`,
|
|
292
299
|
// external
|
|
293
300
|
noSir
|
|
294
301
|
);
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* **IsNumericLiteral**
|
|
3
|
-
*
|
|
4
|
-
* Type utility which returns true/false if the numeric value a _numeric literal_ versus
|
|
5
|
-
* just the _number_ type.
|
|
6
|
-
*/
|
|
7
|
-
export type IsNumericLiteral<T extends number> = number extends T ? false : true;
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* **IfNumericLiteral**
|
|
11
|
-
*
|
|
12
|
-
* Branch utility which returns `IF` type when `T` is a numeric literal and `ELSE` otherwise
|
|
13
|
-
*/
|
|
14
|
-
export type IfNumericLiteral<T extends number, IF, ELSE> = IsNumericLiteral<T> extends true
|
|
15
|
-
? IF
|
|
16
|
-
: ELSE;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* **IsStringLiteral**
|
|
3
|
-
*
|
|
4
|
-
* Type utility which returns true/false if the string a _string literal_ versus
|
|
5
|
-
* just the _string_ type.
|
|
6
|
-
*/
|
|
7
|
-
export type IsStringLiteral<T> = [T] extends [string] ? (string extends T ? false : true) : false;
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* **IfStringLiteral**
|
|
11
|
-
*
|
|
12
|
-
* Branch utility which returns `IF` type when `T` is a string literal and `ELSE` otherwise
|
|
13
|
-
*/
|
|
14
|
-
export type IfStringLiteral<T, IF, ELSE> = [IsStringLiteral<T>] extends [true] ? IF : ELSE;
|