diff --git a/.changeset/bright-eagles-happen.md b/.changeset/bright-eagles-happen.md new file mode 100644 index 00000000..1b6f185e --- /dev/null +++ b/.changeset/bright-eagles-happen.md @@ -0,0 +1,5 @@ +--- +"@clack/prompts": minor +--- + +Improve types for select/multiselect prompts. Numbers and booleans are now supported as the `value` option. diff --git a/packages/prompts/src/index.ts b/packages/prompts/src/index.ts index 2ef983bb..8163a3e1 100644 --- a/packages/prompts/src/index.ts +++ b/packages/prompts/src/index.ts @@ -105,32 +105,33 @@ export const confirm = (opts: ConfirmOptions) => { }).prompt() as Promise; }; -interface Option> { +type Primitive = Readonly; +interface Option { value: Value; label?: string; hint?: string; } -export interface SelectOptions[], Value extends Readonly> { +export interface SelectOptions[], Value extends Primitive> { message: string; options: Options; initialValue?: Options[number]["value"]; } -export interface MultiSelectOptions[], Value extends Readonly> { +export interface MultiSelectOptions[], Value extends Primitive> { message: string; options: Options; initialValue?: Options[number]['value'][]; cursorAt?: Options[number]["value"] } -export const select = [], Value extends Readonly>( +export const select = [], Value extends Primitive>( opts: SelectOptions ) => { const opt = ( option: Options[number], state: "inactive" | "active" | "selected" | "cancelled" ) => { - const label = option.label ?? option.value; + const label = option.label ?? String(option.value); if (state === "active") { return `${color.green("●")} ${label} ${ option.hint ? color.dim(`(${option.hint})`) : "" @@ -174,9 +175,9 @@ export const select = [], Value extends Readonly; }; -export const multiselect = [], Value extends Readonly>(opts: MultiSelectOptions) => { +export const multiselect = [], Value extends Primitive>(opts: MultiSelectOptions) => { const opt = (option: Options[number], state: 'inactive' | 'active' | 'selected' | 'active-selected' | 'submitted' | 'cancelled') => { - const label = option.label ?? option.value; + const label = option.label ?? String(option.value); if (state === 'active') { return `${color.cyan('◻')} ${label} ${option.hint ? color.dim(`(${option.hint})`) : ''}` } else if (state === 'selected') {