Functional Weave
Code in Rust

health.egfr@1.0.1

impl/typescript.ts

2,263 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 { pow } from "./math_pow.ts";  ← from math.pow ^1.0.0 · built alongside by fune
import { roundFloat } from "./math_round_float.ts";  ← from math.round-float ^1.0.0 · built alongside by fune
import { type CreatinineUnit, type Egfr, type Sex } from "./health_egfr_types.ts";

/** Inker et al. 2021, footnote to table 2: mg/dL × 88.4 = µmol/L. */
const UMOL_PER_MG_DL = 88.4;

/**
 * Estimated GFR by the CKD-EPI 2021 creatinine equation without race
 * (Inker et al., NEJM 2021;385:1737-49, table 2):
 *
 *   eGFR = 142 × min(Scr/κ, 1)^α × max(Scr/κ, 1)^-1.200 × 0.9938^age × 1.012 [if female]
 *
 * with Scr in mg/dL, κ 0.7 (female) or 0.9 (male), α -0.241 (female) or
 * -0.302 (male). Powers go through math.pow so all three languages produce
 * the same double; the whole-number result is rounded from the unrounded
 * estimate, never from the one-decimal value (143.4993 is 143, not 144).
 */
export function egfrCkdEpi2021(creatinine: number, unit: CreatinineUnit, ageYears: number, sex: Sex): Egfr {
  let low: number;
  let high: number;
  if (unit === "umol-per-l") {
    low = 10;
    high = 4000;
  } else if (unit === "mg-per-dl") {
    low = 0.1;
    high = 45;
  } else {
    throw new RangeError(`unit must be umol-per-l or mg-per-dl, received ${unit}`);
  }
  if (typeof creatinine !== "number" || !Number.isFinite(creatinine) || creatinine < low || creatinine > high) {
    throw new RangeError(`creatinine must be a number from ${low} to ${high} ${unit}, received ${creatinine}`);
  }
  if (!Number.isInteger(ageYears) || ageYears < 18 || ageYears > 120) {
    throw new RangeError(`ageYears must be a whole number from 18 to 120, received ${ageYears}`);
  }
  if (sex !== "female" && sex !== "male") {
    throw new RangeError(`sex must be female or male, received ${sex}`);
  }
  const female = sex === "female";
  const scr = unit === "umol-per-l" ? creatinine / UMOL_PER_MG_DL : creatinine;
  const kappa = female ? 0.7 : 0.9;
  const alpha = female ? -0.241 : -0.302;
  const ratio = scr / kappa;
  // Below the knot the max() term is 1, above it the min() term is 1.
  const creatinineTerm = ratio <= 1 ? pow(ratio, alpha) : pow(ratio, -1.2);
  let estimate = 142 * creatinineTerm * pow(0.9938, ageYears);
  if (female) estimate = estimate * 1.012;
  return { value: roundFloat(estimate, 1), reported: roundFloat(estimate, 0) };
}