Assist_Design/packages/domain/src/array-utils.ts
T. Narantuya 001de16e38 Add domain types and utilities for customer portal
- Introduced new TypeScript types for catalog products, including Internet, SIM, and VPN plans, along with their respective addons and installation options.
- Created a new domain package with essential configurations, including package.json and tsconfig.json for TypeScript support.
- Added common types and utility functions for type safety and data handling across the application.
- Established a structured export pattern for domain types, enhancing organization and accessibility for future development.
2025-09-17 18:43:31 +09:00

109 lines
2.6 KiB
TypeScript

/**
* Modern array utilities leveraging ES2024 features
*/
/**
* Group array items by a key using ES2024 Object.groupBy
* This is more efficient than manual grouping
*/
export function groupBy<T, K extends PropertyKey>(
array: T[],
keyFn: (item: T) => K
): Record<K, T[]> {
return array.reduce(
(groups, item) => {
const key = keyFn(item);
(groups[key] ??= []).push(item);
return groups;
},
{} as Record<K, T[]>
);
}
/**
* Chunk array into smaller arrays of specified size
* Uses modern array methods for efficiency
*/
export function chunk<T>(array: T[], size: number): T[][] {
if (size <= 0) return [];
const chunks: T[][] = [];
for (let i = 0; i < array.length; i += size) {
chunks.push(array.slice(i, i + size));
}
return chunks;
}
/**
* Get unique items from array with optional key function
* Leverages Set for better performance
*/
export function unique<T>(array: T[]): T[];
export function unique<T, K>(array: T[], keyFn: (item: T) => K): T[];
export function unique<T, K>(array: T[], keyFn?: (item: T) => K): T[] {
if (!keyFn) {
return [...new Set(array)];
}
const seen = new Set<K>();
return array.filter(item => {
const key = keyFn(item);
if (seen.has(key)) {
return false;
}
seen.add(key);
return true;
});
}
/**
* Safe array access using ES2024 .at() method
* Returns undefined for out-of-bounds access
*/
export function safeAt<T>(array: T[], index: number): T | undefined {
return array.at?.(index) ?? array[index];
}
/**
* Partition array into two arrays based on predicate
*/
export function partition<T>(array: T[], predicate: (item: T) => boolean): [T[], T[]] {
const truthy: T[] = [];
const falsy: T[] = [];
for (const item of array) {
if (predicate(item)) {
truthy.push(item);
} else {
falsy.push(item);
}
}
return [truthy, falsy];
}
/**
* Modern intersection of arrays
*/
export function intersection<T>(...arrays: T[][]): T[] {
if (arrays.length === 0) return [];
if (arrays.length === 1) return [...arrays[0]];
const [first, ...rest] = arrays;
const sets = rest.map(arr => new Set(arr));
return first.filter(item => sets.every(set => set.has(item)));
}
/**
* Safe array operations that return null on empty arrays
*/
export const SafeArray = {
first: <T>(array: T[]): T | null => array[0] ?? null,
last: <T>(array: T[]): T | null => array.at?.(-1) ?? array[array.length - 1] ?? null,
random: <T>(array: T[]): T | null => {
if (array.length === 0) return null;
return array[Math.floor(Math.random() * array.length)];
},
} as const;