-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcoercion.library.ts
More file actions
75 lines (64 loc) · 2.74 KB
/
Copy pathcoercion.library.ts
File metadata and controls
75 lines (64 loc) · 2.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import { clone, stringify } from '#library/serialize.library.js';
import { asType } from '#library/type.library.js';
import { isIntegerLike, isArrayLike, isDefined, isInteger, isIterable, isNullish, isString, isUndefined, isNumber, isNumeric } from '#library/assertion.library.js';
/** Coerce {value} into {value[]} ( if not already ), with optional {fill} Object */
export function asArray<T>(arr: Exclude<ArrayLike<T>, string> | undefined): T[];
export function asArray<T>(arr: T | Exclude<Iterable<T> | undefined, string>): NonNullable<T>[];
export function asArray<T, K>(arr: Iterable<T> | ArrayLike<T>, fill: K): K[];
export function asArray<T, K>(arr: T | Iterable<T> | ArrayLike<T> = [], fill?: K): (T | K)[] {
switch (true) {
case isArrayLike<T>(arr): // allow for {length:nn} objects
case isIterable<T>(arr) && !isString(arr): // dont iterate Strings
return Array.from<T, K>(arr, val => {
return isUndefined(fill) || isDefined(val)
? val as unknown as K // if no {fill}, then use {val}
: clone(fill) // clone {fill} to create new Objects
});
default:
return Array.of(arr);
}
}
/** stringify if not nullish */
export function asString<T>(str?: T) {
return isNullish(str)
? ''
: isInteger(str)
? str.toString() + 'n'
: stringify(str);
}
/** convert String | Number | BigInt to Number */
export function asNumber(str?: string | number | bigint) {
return parseFloat(str?.toString() ?? 'NaN');
}
/** convert String | Number to BigInt */
export function asInteger<T extends string | number | bigint>(str?: T) {
const arg = asType(str);
switch (arg.type) {
case 'BigInt':
return arg.value; // already a BigInt
case 'Number':
return BigInt(Math.trunc(arg.value)); // cast as BigInt
case 'String':
return (isIntegerLike(arg.value)) // String representation of a BigInt
? BigInt(arg.value.slice(0, -1)) // get rid of trailing 'n'
: BigInt(arg.value);
default:
return str as Exclude<T, string | number>;
}
}
/** return as Number if possible, else original String */
export const ifNumeric = (str: string | number | bigint, stripZero = false) => {
switch (true) {
case isInteger(str): // BigInt → Number
return Number(str);
case isNumber(str): // Number → as-is
return str;
case isNumeric(str) && (!str?.toString().startsWith('0') || stripZero):
return asNumber(str); // numeric String → Number
default:
return str as string; // non-numeric String → as-is
}
}
export const nullishToZero = <T>(obj: T) => obj ?? 0;
export const nullishToEmpty = <T>(obj: T) => obj ?? '';
export const nullishToValue = <T, R>(obj: T, value: R) => obj ?? value;