function requireNoNilElements<T>(values: T[], message?: string): NonNullable<T>[];
function requireNoNilElements<T>(values: readonly T[], message?: string): readonly NonNullable<T>[];
function requireNoNilElements<T>(values: Set<T>, message?: string): Set<NonNullable<T>>;
function requireNoNilElements<K, V>(values: Map<K, V>, message?: string): Map<K, NonNullable<V>>;
function requireNoNilElements<T extends null | undefined>(values: T, message?: string): T;
function requireNoNilElements(values: unknown, message?: string): unknown;
A collection with a hole in it passes every other guard: it is non-null, non-empty and a valid array. The gap surfaces much later as a blank cell or a Cannot read properties of undefined. This catches it at the boundary, and hands the collection back typed without the nils.
Accepts an array, a Set, or a Map — for a Map the values are checked, not the keys.
A null or undefined collection passes straight through: that case belongs to requireNonNull, and stacking the two guards should not report it twice.
An empty collection passes.
Only the top level is examined; a nested array is opaque.
Array holes count as undefined, so [1, , 3] is rejected.
Parameters
Parameter
Type
Description
values
unknown
The collection to check.
message(optional)
string
The exception message. A default is used when omitted.
Returns
unknown — The same collection object, typed without null and undefined in its element type.
Throws
Exception
Condition
IllegalArgumentException
An element is null or undefined.
IllegalArgumentException
values is neither an array, a Set, nor a Map.
Examples
Checking a row before writing it
/**
* Appends a contact row, refusing a row with a gap in it rather than writing a
* blank cell that shows up as a bug days later.
*/
export function appendContact(
sheet: GoogleAppsScript.Spreadsheet.Sheet,
name: string | null,
email: string | null
): void {
const row = requireNoNilElements([name, email], "name and email are both required");
sheet.getRange(sheet.getLastRow() + 1, 1, 1, row.length).setValues([row]);
}
function appendContact(sheet, name, email) {
const row = requireNoNilElements([name, email], "name and email are both required");
sheet.getRange(sheet.getLastRow() + 1, 1, 1, row.length).setValues([row]);
}
Narrowing the element type
import { requireNoNilElements } from "apps-script-utils";
const values: Array<string | null> = readColumn();
const names: string[] = requireNoNilElements(values, "the column has empty cells");
What passes and what throws
requireNoNilElements([1, 2, 3]); // => [1, 2, 3] — the same array
requireNoNilElements(new Map([["a", 1]])); // => the same Map
requireNoNilElements([]); // => []
requireNoNilElements(null); // => null — not this guard's concern
requireNoNilElements([1, undefined, 3]); // throws IllegalArgumentException
requireNoNilElements([1, , 3]); // throws — a hole is undefined
See also
compact — removes the empty values instead of rejecting them.