type Value = string | number | boolean | null | undefined | Value[] | { [key: string]: Value }; export function arrayDedup(arr: T[]): T[] { const seen = new Map(); for (const item of arr) { const key = stableStringify(item); if (!seen.has(key)) { seen.set(key, item); } } return Array.from(seen.values()); } /** * Deterministic stringify: * - sorts object keys * - preserves arrays order * - distinguishes undefined/null */ function stableStringify(value: Value): string { if (value === undefined) return 'undefined'; if (value === null) return 'null'; if (Array.isArray(value)) { return `[${value.map(stableStringify).join(',')}]`; } if (typeof value === 'object') { const keys = Object.keys(value).sort(); return `{${keys.map((k) => `${k}:${stableStringify(value[k])}`).join(',')}}`; } return `${typeof value}:${String(value)}`; }