/** * Canonical "no value" placeholder for the IMS frontend (#691). * * Missing/null/empty values must render identically everywhere. Route every * display fallback through {@link EMPTY} (or the {@link displayValue} helper) * instead of writing ad-hoc `?? "-"` / `?? "—"` literals, so the placeholder * stays consistent and there is a single place to change it. * * This is a *display* concept only. It does NOT apply to non-display empties * such as date-field form values, CSV cells, or URL query params, which * legitimately use an empty string. */ export const EMPTY = "—"; /** * Coerce a possibly-missing value to a display string, falling back to the * canonical {@link EMPTY} placeholder for: * - `null` / `undefined`, * - blank/whitespace-only strings, and * - non-finite numbers (`NaN`, `Infinity`) — so a missing amount renders * "—" instead of a raw "NaN". * * Finite numbers and non-blank strings are returned as their string form, and * booleans/bigints are stringified. Objects, symbols, and functions have no * meaningful display string (`String({})` is "[object Object]"), so they also * fall back to {@link EMPTY}. */ export function displayValue(value: unknown): string { if (value == null) return EMPTY; if (typeof value === "number") { return Number.isFinite(value) ? String(value) : EMPTY; } if (typeof value === "string") { return value.trim() === "" ? EMPTY : value; } if (typeof value === "boolean" || typeof value === "bigint") { return String(value); } // Objects, symbols, and functions have no meaningful display string // (`String({})` is "[object Object]"), so treat them as "no value". return EMPTY; }