Typescript Array / Iterable Helpers

Date: 2025-04-22
type IterableKind<T> = Iterable<T> | T[];

export function ensureArray<T>(data?: IterableKind<T>): T[] {
    if (!data) return [];
    if (Array.isArray(data)) return data;
    if (typeof data === "string") return [data];
    if (data instanceof Map) return [];
    return Array.from(data);
}

export function firstItem<T>(data?: IterableKind<T>): T | undefined {
    return ensureArray(data)[0];
};

export function arraySum<T>(arr: IterableKind<T>, fn: (arg: T) => number): number {
    return ensureArray(arr).reduce((p, c) => p + fn(c), 0);
}

export function arrayMin<T>(arr: IterableKind<T>, fn: (arg: T) => number): number | undefined {
    const values = ensureArray(arr).map(fn);
    return values.length ? Math.min.apply(Math, values) : undefined;
}

export function arrayMax<T>(arr: IterableKind<T>, fn: (arg: T) => number): number | undefined {
    const values = ensureArray(arr).map(fn);
    return values.length ? Math.max.apply(Math, values) : undefined;
}

export function createMap<TSource, TKey, TValue>(items: Iterable<TSource>, keySelector: (x: TSource) => TKey, valueSelector: (x: TSource) => TValue): Map<TKey, TValue> {
    const m = new Map<TKey, TValue>();
    for (const item of items) {
        const key = keySelector(item);
        const value = valueSelector(item);
        m.set(key, value);
    }
    return m;
}

export function distinctBy<T, K>(array: IterableKind<T>, keySelector: (item: T) => K): T[] {
    const seen = new Map<K, T>();
    for (const item of array) {
        const key = keySelector(item);
        if (!seen.has(key)) {
            seen.set(key, item);
        }
    }
    return Array.from(seen.values());
}
94630cookie-checkTypescript Array / Iterable Helpers