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
|
export type Maybe<T> = T | null | undefined;
export function toNumber(
value: Maybe<number | bigint | string>,
fallback = 0,
): number {
if (value === null || value === undefined) return fallback;
if (typeof value === "number") {
if (Number.isFinite(value)) return value;
return fallback;
}
if (typeof value === "bigint") {
// safe conversion for typical values (timestamps, sizes). Might overflow for huge bigint.
return Number(value);
}
if (typeof value === "string") {
const n = Number(value);
return Number.isFinite(n) ? n : fallback;
}
return fallback;
}
/**
* Like `toNumber` but ensures non-negative result (clamps at 0).
*/
export function toNonNegativeNumber(
value: Maybe<number | bigint | string>,
fallback = 0,
): number {
const n = toNumber(value, fallback);
return n < 0 ? 0 : n;
}
export function toDate(
value: Maybe<number | bigint | string>,
opts?: { isSeconds?: boolean },
): Date | null {
if (value === null || value === undefined) return null;
const isSeconds = opts?.isSeconds ?? true;
// accept bigint, number, numeric string
const n = toNumber(value, NaN);
if (Number.isNaN(n)) return null;
const ms = isSeconds ? Math.floor(n) * 1000 : Math.floor(n);
return new Date(ms);
}
/**
* Convert a binding boolean-ish value (0/1, "true"/"false", boolean) to boolean.
*/
export function toBoolean(value: unknown, fallback = false): boolean {
if (value === null || value === undefined) return fallback;
if (typeof value === "boolean") return value;
if (typeof value === "number") return value !== 0;
if (typeof value === "string") {
const s = value.toLowerCase().trim();
if (s === "true" || s === "1") return true;
if (s === "false" || s === "0") return false;
}
return fallback;
}
|