export function exactlyOne(input: ReadonlyArray, property: string): T { if (input.length !== 1) { throw new Error( `Expected exactly one element for ${property}, got ${input.length}` ); } return input[0]; } export function optionalOne( input: ReadonlyArray, property: string ): T | undefined { if (input.length > 1) { throw new Error( `Expected one optional element for ${property}, got ${input.length}` ); } return input[0]; } export function required( input: T | undefined, property: string ): NonNullable { if (input == null) { throw new Error(`Expected a value for ${property}, got undefined`); } return input; } export function allRequired( input: ReadonlyArray, property: string ): Array> { return input.map((v, i) => required(v, `${property}[${i}]`)); } export function atLeastOne( input: ReadonlyArray, property: string ): ReadonlyArray { if (input.length === 0) { throw new Error(`Expected at least one element for ${property}`); } return input; } export function atLeastOneAndAllRequired( input: ReadonlyArray, property: string ): ReadonlyArray> { return atLeastOne(allRequired(input, property), property); } export function valueForKey(input: Record, key: string): T { return required(input[key], key); } export function valuesForKeys( input: Record, keys: string[] ): T[] { return keys.map((key) => valueForKey(input, key)); }