Documentation / Array

Array

Utilities for transforming, grouping, and structuring arrays. Import from the root or from koyojs/Array.

// Root import
import { chunk, flatten, unique, groupBy, createArray } from "koyojs";

// Per-module import
import { chunk } from "koyojs/Array";
chunkchunk<T>(arr: T[], size: number): T[][]

Splits an array into sub-arrays of the given size. The last chunk may be smaller if the array length is not evenly divisible.

ParameterTypeDescription
arrT[]The source array.
sizenumberThe maximum length of each chunk. Must be a positive integer.
returnsT[][]
import { chunk } from "koyojs";

chunk([1, 2, 3, 4, 5], 2);   // [[1, 2], [3, 4], [5]]
chunk(["a","b","c","d"], 3);  // [["a","b","c"], ["d"]]
chunk([], 2);                  // []

// Pagination — split all items into pages of 10
const pages = chunk(allProducts, 10);
const currentItems = pages[pageIndex] ?? [];

// Batch API requests — process 50 IDs at a time to avoid rate limits
const batches = chunk(userIds, 50);
for (const batch of batches) {
  await api.bulkUpdate(batch);
}

// Render a fixed 3-column grid
const rows = chunk(items, 3);
rows.map(row => (
  <div class="grid-row">
    {row.map(item => <Card item={item} />)}
  </div>
));

flattenflatten<T>(arr: unknown[]): T[]

Recursively flattens a nested array of any depth into a single flat array.

ParameterTypeDescription
arrunknown[]The nested array to flatten.
returnsT[]
import { flatten } from "koyojs";

flatten([1, [2, 3], [4, [5, 6]]]);  // [1, 2, 3, 4, 5, 6]
flatten([[["a"]], ["b"], "c"]);      // ["a", "b", "c"]
flatten([]);                         // []

// Collect all tags from multiple blog posts into one list
const posts = [
  { title: "Intro to TS",   tags: ["typescript", "beginner"] },
  { title: "Advanced TS",   tags: ["typescript", "advanced"] },
  { title: "SolidJS Guide", tags: ["solidjs", "frontend"] },
];
const allTags = flatten(posts.map(p => p.tags));
// ["typescript", "beginner", "typescript", "advanced", "solidjs", "frontend"]

// Flatten a matrix into a 1D array
const matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
flatten(matrix);  // [1, 2, 3, 4, 5, 6, 7, 8, 9]

// Normalize API response with nested arrays
const categorized = await fetch("/api/products").then(r => r.json());
// { featured: [...], popular: [...], new: [...] }
const allProducts = flatten(Object.values(categorized));

unique / removeDuplicatesunique<T>(arr: T[]): T[]

Returns a new array with all duplicate values removed. Preserves the order of first occurrence. `removeDuplicates` is an alias for the same function.

ParameterTypeDescription
arrT[]The input array.
returnsT[]
import { unique, removeDuplicates } from "koyojs";

unique([1, 2, 2, 3, 1, 4]);    // [1, 2, 3, 4]
unique(["a", "b", "a", "c"]);  // ["a", "b", "c"]
unique([]);                     // []

// removeDuplicates is an alias — identical behaviour
removeDuplicates([1, 1, 2]);  // [1, 2]

// Deduplicate tags entered by a user
const rawTags = ["js", "typescript", "js", "css", "typescript"];
const tags = unique(rawTags);  // ["js", "typescript", "css"]

// Collect unique user IDs from an event log
const activeUserIds = unique(events.map(e => e.userId));

// Merge two lists without duplicates
const merged = unique([...existingItems, ...newItems]);

// Get all distinct categories from a product catalog
const categories = unique(products.map(p => p.category));

groupBygroupBy<T>(arr: T[], keyFn: (item: T) => string): Record<string, T[]>

Groups the elements of an array into an object keyed by the string returned by `keyFn`. Each key maps to an array of all elements that produced that key.

ParameterTypeDescription
arrT[]The array to group.
keyFn(item: T) => stringA function that receives each element and returns the group key.
returnsRecord<string, T[]>
import { groupBy } from "koyojs";

// Group employees by department
const people = [
  { name: "Alice", dept: "eng" },
  { name: "Bob",   dept: "design" },
  { name: "Carol", dept: "eng" },
];

groupBy(people, p => p.dept);
// {
//   eng:    [{ name: "Alice", dept: "eng" }, { name: "Carol", dept: "eng" }],
//   design: [{ name: "Bob",   dept: "design" }],
// }

// Group numbers by parity
groupBy([1, 2, 3, 4, 5], n => n % 2 === 0 ? "even" : "odd");
// { odd: [1, 3, 5], even: [2, 4] }

// Group orders by status for a dashboard
const grouped = groupBy(orders, o => o.status);
const pendingCount  = grouped.pending?.length  ?? 0;
const shippedCount  = grouped.shipped?.length  ?? 0;
const deliveredCount = grouped.delivered?.length ?? 0;

// Group log entries by severity level
const logs = groupBy(entries, e => e.level);  // { info: [...], warn: [...], error: [...] }

createArraycreateArray<T>(options: TypedArrayOptions<T>): TypedArray<T>

Creates a type-enforced array that validates each element on push. When `strict` is true, pushing an invalid value throws a TypeError. When false, it logs a warning and silently drops the value. An optional `validate` predicate lets you enforce any type or shape beyond primitives.

ParameterTypeDescription
options.strictbooleanIf true, invalid pushes throw TypeError. If false, they warn and are silently dropped.
options.validate(value: unknown) => value is TOptional type guard. Defaults to checking the type of the first element pushed.
returnsTypedArray<T>
import { createArray } from "koyojs";

// Strict number array — throws on bad input
const nums = createArray<number>({ strict: true });
nums.push(1, 2, 3);  // ok
nums.push("oops");   // throws TypeError: expected number, got string

// Lenient string array — warns and skips invalid values
const tags = createArray<string>({
  strict: false,
  validate: (v): v is string => typeof v === "string",
});
tags.push("alpha", "beta");  // ok
tags.push(42);               // console.warn, dropped silently
console.log(tags.items);     // ["alpha", "beta"]
console.log(tags.toArray()); // ["alpha", "beta"]  — plain JS array

// TypedArray is iterable
for (const tag of tags) console.log(tag);

// Custom shape validation for a typed entity list
interface Product { id: number; name: string; price: number }

const isProduct = (v: unknown): v is Product =>
  typeof v === "object" && v !== null &&
  "id" in v && "name" in v && "price" in v;

const cart = createArray<Product>({ strict: true, validate: isProduct });
cart.push({ id: 1, name: "Keyboard", price: 89.99 });  // ok
cart.push({ id: 2, name: "Mouse" });                   // throws — missing price

// Get the total from a typed cart
import { sum } from "koyojs";
const total = sum(cart.items.map(p => p.price));