arrify

Convert any value to an array, safely handling null, undefined, strings, and iterables.

Library
npm
v3.0.0
133stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
39/100Needs Attention
Development Activity0
Maintenance20
Community64
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
54/100Fair
Architecture65
Code Quality80
Innovation35
Learning Curve35

arrify is a tiny utility from Sindre Sorhus that normalizes any JavaScript value into an array. It treats null and undefined as an empty array, passes existing arrays through unchanged, wraps strings as a single-element array instead of splitting them into characters, and spreads any iterable (a Set, a Map, a generator) into a proper array via Symbol.iterator. Everything else falls back to a single-element array.

The package is distributed as a single ESM file with bundled TypeScript definitions that use conditional types to infer the precise return type for each input shape — arrify('x') types as [string], arrify(mySet) types as T[], and so on. It has no runtime dependencies and is commonly reached for whenever an API needs to accept either a single value or a collection of values.

What You Get

  • A single default-exported arrify() function with no configuration or options object.
  • Bundled TypeScript definitions with conditional types that infer the exact return type per input shape.
  • ESM-only distribution (type: module, single exports entry) with zero runtime dependencies.
  • Consistent null/undefined handling — both normalize to an empty array rather than throwing.

Common Use Cases

  • Normalizing function arguments - Library authors accepting string | string[]-style options call arrify() once and iterate without branching.
  • CLI flag handling - CLI tools that let a flag be passed once or repeated can arrify the parsed value into a consistent array.
  • Safe optional-array defaults - Code paths that may receive null/undefined for an “items” field arrify it into [] instead of null-checking everywhere.
  • Converting Set/Map results to arrays - Consumers of Set- or Map-based APIs arrify the result for .map()/.filter() chaining.

Under The Hood

Architecture The entire package is one exported function in index.js that runs a short sequence of type checks — null/undefined first, then Array.isArray, then typeof value === 'string', then a Symbol.iterator check for other iterables, with a final fallback that wraps the value in a single-element array. There are no internal layers, no dependency injection, and no state; the only “architecture” is the ordering of these checks, which matters because strings are themselves iterable and must be special-cased before the generic iterable branch.

Tech Stack The runtime code has zero dependencies and ships as native ESM ("type": "module", single exports field, Node >=12 engine constraint). Tooling is entirely dev-time: ava for unit tests, tsd for type-level assertions against the hand-written index.d.ts, and xo (Sindre Sorhus’s opinionated ESLint preset) for linting — all invoked from a single npm test script. No bundler or build step is needed since the published files are the same plain JS/.d.ts files in the repo.

Code Quality Test coverage in test.js exercises the main branches (string, Map, Set, null, undefined, and array-identity preservation) using ava, and index.test-d.ts separately asserts the inferred TypeScript types for a wide range of input shapes via tsd. A GitHub Actions workflow runs this full suite across Node 12, 14, and 16 on every push and PR. The function itself has no error handling because it cannot fail — every input maps to some array output — and naming is minimal and clear given the tiny surface area.

What Makes It Unique The runtime behavior itself is a standard normalization utility comparable to Lodash’s castArray. What sets it apart is the type-level precision: the bundled conditional types compute the literal return type for each input variant (a string input types as a one-tuple, an array passes through as-is, an iterable resolves to its element type), which is more exact than most similarly small utilities bother to provide.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search