function to_array(value, n) {
	// return arrays unchanged
	if (Array.isArray(value)) {
		return value;
	}

	// if value is not iterable, or `n` is unspecified (indicates a rest
	// element, which means we're not concerned about unbounded iterables)
	// convert to an array with `Array.from`
	if (n === undefined || !(Symbol.iterator in value)) {
		return Array.from(value);
	}

	// otherwise, populate an array with `n` values

	/** @type {T[]} */
	const array = [];

	for (const element of value) {
		array.push(element);
		if (array.length === n) break;
	}

	return array;
}
When encountering a situation like `let [a, b, c] = $derived(blah())`,
we need to stash an intermediate value that `a`, `b`, and `c` derive
from, in case it's an iterable
@template T
@param {ArrayLike<T> | Iterable<T>} value
@param {number} [n]
@returns {Array<T>}