README.md

May 3, 2026 · View on GitHub


Logo ArrayMixer

ArrayMixer is a tiny TypeScript-friendly utility (< 1 kB gzipped) for interleaving any number of arrays in a fully customizable order.
Powerful, dependency-free, and easy to use.

Table of contents

What's new in v1

The previous ArrayMixer(aliases, sequence) API based on a string mini-DSL (["2C", "4M"]) was replaced by a clean, type-safe tuple-based API:

// before (v0.x)
ArrayMixer({ P: photos, A: ads }, ["2P", "1A"]);

// after (v1.x)
arrayMixer([2, photos], [1, ads]);

Why the change:

  • No mini-DSL — sequences are plain data, no string parsing.
  • No aliases — the source array is right there in the entry.
  • Generic types — the result type is inferred from the inputs.
  • Options object — opt into limit, shuffle, and fill strategies.

Documentation

Open the official docs page at ArrayMixer Docs for package manager commands, ESM, CommonJS, browser UMD, and TypeScript notes.

Installation

pnpm add array-mixer
import { arrayMixer } from "array-mixer";

CommonJS, ESM, and a UMD bundle are all shipped. For a <script> tag:

<script src="https://unpkg.com/array-mixer/release/array-mixer.umd.js"></script>
<script>
  const mixed = ArrayMixer.arrayMixer([2, photos], [1, ads]);
</script>

Playground

Try the tuple API in the ArrayMixer Playground.

Quick start

Given two arrays, photos (12 items) and ads (6 items):

photos.length === 12; // true
ads.length === 6;     // true

Interleave 2 photos followed by 1 ad until both arrays are consumed:

const mixed = arrayMixer([2, photos], [1, ads]);

mixed will contain:

API

arrayMixer(...entries, options?)

Reorder one or more arrays into a single array by interleaving chunks of each.

function arrayMixer<T>(...entries: MixEntry<T>[]): T[];
function arrayMixer<T>(
  ...args: [...MixEntry<T>[], MixerOptions]
): T[];

The optional options object is detected automatically as the last argument when it is not a MixEntry tuple.

MixEntry<T>

type MixEntry<T> = readonly [count: number, items: readonly T[]];

A tuple with two fields:

  • count — how many items of this group to emit per round. Must be a positive integer.
  • items — the source array.

MixerOptions

interface MixerOptions {
  limit?: number;
  shuffle?: boolean;
  fill?: "repeat" | "skip" | "stop";
}
OptionDefaultDescription
limitsum of input lengthsForces a fixed result length. Useful for infinite feeds.
shufflefalseShuffles each input array (Fisher–Yates) before mixing. Inputs are not mutated.
fill"repeat"What to do when an entry's source runs out: "repeat" cycles from the start, "skip" removes that group from further rounds, "stop" ends the result.

Invalid runtime input throws clear errors:

  • count must be a positive integer.
  • limit, when provided, must be a non-negative integer.
  • fill, when provided, must be "repeat", "skip", or "stop".

Examples

1) For every 7 photos display an ad

arrayMixer([7, photos], [1, ads]);

2) For every 4 paragraphs include 2 images

arrayMixer([4, paragraphs], [2, images]);
arrayMixer([4, related], [2, sponsored], [2, related]);

4) Display a list of songs with hits sprinkled in

arrayMixer([10, songs], [2, hits]);

5) Cycle puppies, kittens, and penguins in sequence

const mixed = arrayMixer([1, puppies], [1, kittens], [1, penguins]);
puppieskittenspenguinsmixed
[🐶, 🐶, 🐶][🐱, 🐱, 🐱][🐧, 🐧, 🐧][🐶, 🐱, 🐧, 🐶, 🐱, 🐧, 🐶, 🐱, 🐧]

6) 1 large photo for every 2 medium followed by 3 small

arrayMixer([2, medium], [3, small], [1, large]);

7) Cap an infinite feed with limit

arrayMixer([3, articles], [1, ads], { limit: 20 });

The result is exactly 20 items long; arrays cycle as needed (fill: "repeat" is the default).

8) Stop when any source runs out

arrayMixer(
  [2, [1, 2, 3, 4]],
  [1, [9]],
  { fill: "stop", limit: 100 },
);
// => [1, 2, 9, 3, 4]

9) Drop exhausted groups, keep the rest going

arrayMixer(
  [1, ["a", "b"]],
  [1, ["x", "y", "z", "w"]],
  { fill: "skip" },
);
// => ["a", "x", "b", "y", "z", "w"]

10) Shuffle each source before mixing

arrayMixer([2, ads], [5, articles], { shuffle: true });

TypeScript support

The result type is inferred from the inputs:

const mixed = arrayMixer([2, ["red", "blue"]], [1, ["cat", "dog"]]);
// mixed: string[]

interface Photo { url: string }
const photos: Photo[] = [/* ... */];
const ads: Photo[] = [/* ... */];

const feed = arrayMixer([2, photos], [1, ads]);
// feed: Photo[]

Contributing

You may contribute in many ways: new features, bug fixes, documentation improvements, or translations. See CONTRIBUTING.md.

License

MIT — Jota Teles

Special thanks