No dependencies whatsoever. This package declares no dependencies or devDependencies.
Permalink to InstallationInstallation
Permalink to Quick TakeQuick Take
Permalink to ExamplesExamples
Purpose
arrayiffy-if-string normalises a value only when that value is a primitive string:
- A non-empty string becomes a one-element array.
- An empty string becomes an empty array.
- Every non-string value passes through unchanged.
Use it when an option accepts either one string or an array of strings, but other values have their own meaning and must retain their identity.
API — arrayiffy()
The main function arrayiffy() is imported like this:
export type StringInABox<T> = T extends string
? T extends ""
? []
: string extends T
? [] | [string]
: [T]
: T;
declare function arrayiffy<T>(something: T): StringInABox<T>;
The function takes one required input:
| Input | Return value |
|---|---|
| Non-empty primitive string | |
| Non-empty primitive string | A fresh one-element array containing that string |
| Empty primitive string | |
| Empty primitive string | A fresh empty array |
| Any non-string value | |
| Any non-string value | The original value, returned by identity |
Runtime behavior
Each primitive string call allocates a new array:
import { strict as assert } from "node:assert";
import { arrayiffy } from "arrayiffy-if-string";
const first = arrayiffy("alpha");
const second = arrayiffy("alpha");
assert.deepEqual(first, ["alpha"]);
assert.notEqual(first, second);
const firstEmpty = arrayiffy("");
const secondEmpty = arrayiffy("");
assert.deepEqual(firstEmpty, []);
assert.notEqual(firstEmpty, secondEmpty);
Non-string values are not cloned, converted, or wrapped. Arrays, objects, functions, symbols, bigints, numbers, booleans, null, undefined, dates, regular expressions, and boxed String objects all pass through by identity:
import { strict as assert } from "node:assert";
import { arrayiffy } from "arrayiffy-if-string";
const settings = { enabled: true };
const existingArray = ["alpha"];
const boxedString = Object("alpha");
assert.equal(arrayiffy(settings), settings);
assert.equal(arrayiffy(existingArray), existingArray);
assert.equal(arrayiffy(boxedString), boxedString);
assert.equal(arrayiffy(null), null);
A boxed String is an object, not a primitive string. It therefore passes through instead of becoming an array.
Type inference
The exported StringInABox<T> type follows the runtime branches and distributes over unions:
| Input type | Return type |
|---|---|
"" | |
"" | [] |
"alpha" | |
"alpha" | ["alpha"] |
string | |
string | [] | [string] |
unknown | |
unknown | unknown |
any | |
any | any |
{} | |
{} | {} |
String | |
String | String |
"alpha" | 42 | |
"alpha" | 42 | ["alpha"] | 42 |
Broad and boxed inputs do not gain a false array guarantee. For example, an unknown input produces unknown, so TypeScript requires you to narrow the result before using array methods:
import { arrayiffy } from "arrayiffy-if-string";
declare const input: unknown;
const result = arrayiffy(input);
// result: unknown
if (Array.isArray(result)) {
console.log(result.length);
}
Literal and branded primitive strings retain their precise element types:
import { arrayiffy } from "arrayiffy-if-string";
declare const brand: unique symbol;
type UserId = string & { readonly [brand]: true };
declare const userId: UserId;
const boxedUserId = arrayiffy(userId);
// boxedUserId: [UserId]
Comparison with always-wrap helpers
Choose arrayiffy-if-string when non-string values must preserve their existing meaning. A helper that always wraps input serves a different contract: it might turn an object into [object] or map null to an array, while this package returns those values unchanged.
API — version
You can import version: