Functional Weave
Code in Python

insurance.age-banding@1.0.0

impl/typescript.ts

1,932 bytes · the TypeScript implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

import { age } from "./dates_age.ts";  ← from dates.age ^1.0.0 · built alongside by fune
import { type AgeBand, type AgeBanding } from "./insurance_age_banding_types.ts";

/**
 * The policyholder's age on the inception date and the band it falls in.
 *
 * Age is completed years by dates.age, so a 29 February birthday ages on
 * 1 March in other years. The bands are checked before use: youngest first,
 * inclusive at both ends, no overlaps, and only the last may be open-ended.
 * An age no band covers is an error, not the nearest band.
 */
export function ageBand(birthDate: string, inceptionDate: string, bands: readonly AgeBand[]): AgeBanding {
  if (bands.length === 0) throw new RangeError("bands must not be empty");
  let previousMax = -1;
  for (let i = 0; i < bands.length; i++) {
    const band = bands[i];
    if (!Number.isInteger(band.minAge) || band.minAge < 0) {
      throw new RangeError(`minAge must be a whole number of 0 or more, received ${band.minAge}`);
    }
    const open = band.maxAge === null || band.maxAge === undefined;
    if (open && i !== bands.length - 1) {
      throw new RangeError(`only the last band may have no maxAge: "${band.label}" is not last`);
    }
    if (!open && (!Number.isInteger(band.maxAge) || (band.maxAge as number) < band.minAge)) {
      throw new RangeError(`maxAge must be a whole number no less than minAge in band "${band.label}"`);
    }
    if (band.minAge <= previousMax) {
      throw new RangeError(`bands must be youngest first and not overlap: "${band.label}" starts at ${band.minAge}`);
    }
    previousMax = open ? Number.MAX_SAFE_INTEGER : (band.maxAge as number);
  }
  const years = age(birthDate, inceptionDate);
  for (const band of bands) {
    const open = band.maxAge === null || band.maxAge === undefined;
    if (years >= band.minAge && (open || years <= (band.maxAge as number))) {
      return { age: years, label: band.label };
    }
  }
  throw new RangeError(`no band for age ${years}`);
}