Cancel Handling
How termprompt handles Esc and Ctrl+C with type-safe cancellation.
Preview
Active prompt
before cancel
◇ Project name?│ my-a└
After Esc or Ctrl+C
cancelled
■ Project name?│cancelled
The Problem
When a user presses Esc or Ctrl+C, the prompt needs to return something. Returning null or undefined is ambiguous because those could be valid values. Returning false collides with confirm() results.
The Solution
termprompt uses a unique symbol for cancellation. Every prompt returns T | Cancel, and you check with isCancel().
import { input, isCancel } from 'termprompt';
const name = await input({ message: 'Name?' });
if (isCancel(name)) {
// User pressed Esc or Ctrl+C
console.log('Bye');
process.exit(0);
}
// TypeScript now knows `name` is a string
console.log(name.toUpperCase());
Why a Symbol?
isCancel() is a type guard. After the check, TypeScript narrows the type from string | Cancel to string. Full type safety without casting.
const confirmed = await confirm({ message: 'Continue?' });
if (isCancel(confirmed)) {
// confirmed is Cancel here
process.exit(0);
}
// confirmed is boolean here, not boolean | Cancel
if (confirmed) {
deploy();
}
The CANCEL Symbol
You can also import the symbol directly for comparisons, though isCancel() is preferred.
import { CANCEL } from 'termprompt';
import type { Cancel } from 'termprompt';
// These are equivalent:
if (isCancel(value)) { ... }
if (value === CANCEL) { ... }
With group()
When using group(), cancellation in any prompt stops the entire chain. Use the onCancel callback to handle it.
import { group, input, confirm, log } from 'termprompt';
const answers = await group(
{
name: () => input({ message: 'Name?' }),
proceed: () => confirm({ message: 'Continue?' }),
},
{
onCancel() {
log.warn('Cancelled.');
process.exit(0);
},
},
);
group cancelled on second prompt
◆ Name?│ my-app■ Continue?│cancelled▲ Cancelled.