banking.cheque-amount-words
The words and figures to write on a cheque: "One hundred and twenty pounds and fifty pence only", "£120.50".
1.0.0 · published 2026-10-03 by charlie · Anterra
Pinned by 18 tests, run in TypeScript, Python and Rust.
What it does
The two amount lines of a cheque: the words ("One thousand two hundred and thirty-four pounds and fifty-six pence only") and the figures ("£1,234.56").
It does not spell numbers itself. The words are `text.number-to-words` (`amountInWords`), so the British "and" rules, singular "one penny" and the supported currencies are exactly that capability's; the figures are `money.format`. What this adds is the cheque convention around them.
For example
chequeAmountWords(£1,234.56, words)→ words One thousand two hundred and thirty-four pounds and fifty-six pence only, figures £1,234.56 pounds and pence in wordschequeAmountWords(£120.50, figures)→ words One hundred and twenty pounds and 50p only, figures £120.50 pounds and pence as figureschequeAmountWords(£10.00, words)→ words Ten pounds only, figures £10.00 whole pounds leave the pence out in words
The function
The same function in TypeScript, Python and Rust, pinned by the same tests. Pick your language; the choice follows you around the registry.
export function chequeAmountWords(amount: Money, penceStyle: ChequePenceStyle): ChequeWording
| amount | Money | more than zero; GBP, EUR or USD |
| penceStyle | ChequePenceStyle | words spells the pence out; figures writes them as "50p" |
| returns | ChequeWording | the words line and the figures box |
The types it declares, generated into your project
export type ChequePenceStyle = "words" | "figures";
/** What goes on the two amount lines of a cheque. */
export interface ChequeWording {
/** capitalised, ending "only" */
readonly words: string;
/** e.g. "£1,234.56" */
readonly figures: string;
}
Your code names it in one line, in the file that uses it
import { chequeAmountWords } from "#fune/banking.cheque-amount-words@^1";
Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import { type Money, money } from "./money_amount.ts"; ← from money.amount ^1.0.0 · built alongside by fune
import { formatMoney } from "./money_format.ts"; ← from money.format ^1.0.0 · built alongside by fune
import { amountInWords } from "./text_number_to_words.ts"; ← from text.number-to-words ^1.0.0 · built alongside by fune
import { type ChequePenceStyle, type ChequeWording } from "./banking_cheque_amount_words_types.ts";
/** The abbreviation written after pence as figures: 50p, 50c. */
const MINOR_SUFFIX: { [code: string]: string } = { GBP: "p", EUR: "c", USD: "c" };
/**
* The amount lines of a cheque. The words come from text.number-to-words,
* capitalised and closed with "only" so nothing can be added after them; the
* figures come from money.format.
*/
export function chequeAmountWords(amount: Money, penceStyle: ChequePenceStyle): ChequeWording {
if (amount.minor <= 0) {
throw new RangeError(`a cheque amount must be greater than zero, received ${amount.minor}`);
}
let body: string;
if (penceStyle === "words") {
body = amountInWords(amount);
} else if (penceStyle === "figures") {
// The pounds are always in words, even when there are none, so the line
// never starts with a figure that could be altered.
const major = Math.floor(amount.minor / 100);
const minor = amount.minor % 100;
body = amountInWords(money(major * 100, amount.currency));
if (minor > 0) {
body += ` and ${minor}${MINOR_SUFFIX[amount.currency]}`;
}
} else {
throw new RangeError(`unknown pence style "${penceStyle}": expected words or figures`);
}
const words = `${body.charAt(0).toUpperCase()}${body.slice(1)} only`;
return { words, figures: formatMoney(amount) };
}Install
fune build
With that line in your source, in a TypeScript project (language typescript in fune.project), fune build resolves it and its 3 dependencies, pins them in fune.lock, downloads only the TypeScript package of each, and builds the code above into your project’s .fune/build, one readable file per capability with a header linking back here. Or pin a range in fune.project and build in one step:
fune add banking.cheque-amount-words
The manifest, vectors and README with only the TypeScript implementation. Install it without the registry with fune add ./banking.cheque-amount-words-1.0.0-typescript.fune, or fetch it from a terminal with fune pull banking.cheque-amount-words@1.0.0:typescript.
The whole function, every language, is one file too: banking.cheque-amount-words-1.0.0.fune, 14,328 bytes, sha256 80d0e873ffe7b7ee2442c5a529db085afa8ab56d9a5f17e5a870ca935d0a7a10. It installs into a project of any language.
Customise it in your app
The seams this capability offers. Put a marker directly above a function of your own and fune build wires it into the built code; the package on the registry is not changed, the built file’s header lists it under CUSTOMISED, and fune hooks lists every hook in the project. How hooks work.
before — your function gets the arguments and returns them, changed or not, or throws to refuse the call.
// fune: before banking.cheque-amount-words
after — your function gets the result and the arguments, and returns the final result.
// fune: after banking.cheque-amount-words
replace — inside this capability’s code only, calls to a dependency go to your function, with the same signature. Other capabilities that use it are unaffected; write in * to replace it everywhere.
// fune: replace money.amount in banking.cheque-amount-words
// fune: replace money.format in banking.cheque-amount-words
// fune: replace text.number-to-words in banking.cheque-amount-words
step — your function runs at a numbered point inside the function’s body, receives the in-scope values it names as parameters, and may return replacements. List the points with fune show banking.cheque-amount-words --steps.
// fune: step banking.cheque-amount-words after <n|label>
Tests
A version published now needs at least 8 tests for every function, and one that expects the error for each function that throws; the registry refuses it otherwise. fune verify --all runs each case in TypeScript, Python and Rust, and a project runs them again with fune verify. This page lists the cases; it does not run them. The exact JSON is vectors.json.
| Case | Arguments | Expected | |
|---|---|---|---|
| pounds and pence in words | £1,234.56, words | → | words One thousand two hundred and thirty-four pounds and fifty-six pence only, figures £1,234.56 |
| pounds and pence as figures | £120.50, figures | → | words One hundred and twenty pounds and 50p only, figures £120.50 |
| whole pounds leave the pence out in words | £10.00, words | → | words Ten pounds only, figures £10.00 |
| whole pounds leave the pence out as figures | £10.00, figures | → | words Ten pounds only, figures £10.00 |
| single pence are not padded | £100.05, figures | → | words One hundred pounds and 5p only, figures £100.05 |
| one pound and one penny | £1.01, words | → | words One pound and one penny only, figures £1.01 |
| under a pound in words | £0.50, words | → | words Fifty pence only, figures £0.50 |
| under a pound as figures still writes the pounds in words | £0.50, figures | → | words Zero pounds and 50p only, figures £0.50 |
| the smallest cheque | £0.01, words | → | words One penny only, figures £0.01 |
| British and after hundreds | £101.00, words | → | words One hundred and one pounds only, figures £101.00 |
Show the other 8 tests
| Case | Arguments | Expected | |
|---|---|---|---|
| a million | £1,000,000.00, words | → | words One million pounds only, figures £1,000,000.00 |
| euros | €25.75, words | → | words Twenty-five euros and seventy-five cents only, figures €25.75 |
| euro cents as figures | €25.75, figures | → | words Twenty-five euros and 75c only, figures €25.75 |
| dollars | $1.99, figures | → | words One dollar and 99c only, figures $1.99 |
| a zero cheque is an error | £0.00, words | → | error: a cheque amount must be greater than zero |
| a negative cheque is an error | -£5.00, words | → | error: a cheque amount must be greater than zero |
| a currency without words is an error | ¥500, words | → | error: no words for currency "JPY" |
| an unknown pence style is an error | £5.00, roman | → | error: unknown pence style |
More from the author
## Conventions
- The words line starts with a capital and ends with "only", the traditional guard against words being added after the amount. - `penceStyle` `words` spells the pence out; `figures` writes them as a number with "p" (GBP) or "c" (EUR, USD): "One hundred and twenty pounds and 50p only". Many UK cheque writers and banks' own guidance use the figures style; both are valid. Single pence are not padded: "and 5p". - Whole amounts leave the pence out in both styles: "Ten pounds only". - In the figures style the pounds are always in words, even when there are none ("Zero pounds and 50p only"), so the line never starts with a figure that could be altered. In the words style an amount under a pound reads "Fifty pence only", as `text.number-to-words` writes it.
## Edge cases
- The amount must be greater than zero: a cheque cannot be written for nothing or for a negative sum. (`text.number-to-words` accepts negatives for credit notes; this does not.) - GBP, EUR and USD only, because those are the currencies `text.number-to-words` has unit names for; anything else fails with its error ("no words for currency"). - US checks conventionally write cents as a fraction ("and 99/100 dollars"); that style is not offered.
Files
| Path | Bytes |
|---|---|
| README.md | 1,731 |
| impl/python.py | 1,429 |
| impl/rust.rs | 2,157 |
| impl/typescript.ts | 1,567 |
| vectors.json | 4,341 |