Types
Cliffy provides some default types which are used to validate user input, providing shell completions and adding infos to the help text. It is also possible to register custom types. You can read more about custom types here.
Types can be declared after the argument name, separated by colon <name:type>
.
If no type is specified, the type defaults to string
. If an option with no
arguments is defined the type defaults to true
.
Built-in types
Following types are available by default on all commands.
- boolean: Can be one of:
true
,false
,1
or0
. - string: Can be any value.
- number: Can be any numeric value.
- integer: Can be any integer value.
- file: Same as string but adds support for path completion.
import { Command } from "@cliffy/command";
const { options } = await new Command()
// Env value must be always required.
.env("DEBUG=<debug:boolean>", "Enable debugging.")
// Option with no value.
.option("-d, --debug", "Enable debugging.")
// Option with optional boolean value.
.option("-s, --small [small:boolean]", "Small pizza size.")
// Option with required string value.
.option("-p, --pizza-type <type>", "Flavour of pizza.")
// Option with required number value.
.option("-a, --amount <amount:integer>", "Pieces of pizza.")
// One required and one optional command argument.
.arguments("<input:file> [output:file]")
.parse(Deno.args);
console.log(options);
Copy
deno run examples/command/common_option_types.ts -p
Error: Missing value for option "--pizza-type".
deno run examples/command/common_option_types.ts -sp vegetarian --amount 3
{ small: true, pizzaType: "vegetarian", amount: 3 }
Copy
Enum type
The EnumType
can be used to define a list of allowed values. The constructor
accepts either an Array<string | number | boolean>
or an enum
. The values
are used for input validation and shell completions and displayed in the help
text and types will be automatically inferred and applied to the values of the
command options and arguments.
import { Command, EnumType } from "@cliffy/command";
enum Animal {
Dog = "dog",
Cat = "cat",
}
// Enum type with enum.
const animal = new EnumType(Animal);
// Enum type with array.
const color = new EnumType(["blue", "yellow", "red"]);
await new Command()
.type("color", color)
.type("animal", animal)
.option(
"-c, --color [name:color]",
"Choose a color.",
)
.option(
"-a, --animal [name:animal]",
"Choose an animal.",
)
.action(({ color, animal }) => {
console.log("color: %s", color);
console.log("animal: %s", animal);
})
.parse(Deno.args);
Copy
deno run examples/command/enum_option_type.ts --color red --animal dog
color: red
animal: dog
deno run examples/command/enum_option_type.ts --color foo
error: Option "--color" must be of type "color", but got "foo". Expected values: "blue", "yellow", "red"
Copy
List types
Each type can be used as a list. A list type accepts a ,
seperated list of
items with the specified type. The default separator is ,
but can be changed
with the separator
option.
import { Command } from "@cliffy/command";
const { options } = await new Command()
// comma separated list
.option("-l, --list <items:number[]>", "comma separated list of numbers.")
// space separated list
.option(
"-o, --other-list <items:string[]>",
"space separated list of strings.",
{ separator: " " },
)
.parse(Deno.args);
console.log(options);
Copy
deno run examples/command/list_option_type.ts -l 1,2,3
{ list: [ 1, 2, 3 ] }
deno run examples/command/list_option_type.ts -o "1 2 3"
{ otherList: [ "1", "2", "3" ] }
Copy
Global types
To make a type also available for child commands, you can use the
.globalType()
method. You can also make a type global with the global
option
in .type()
method.
import { Command, EnumType } from "@cliffy/command";
await new Command()
.globalType("color", new EnumType(["red", "blue", "yellow"]))
.command("foo", "...")
.option("-c, --color <name:color>", "Chose a color.")
.action(console.log)
.command("bar", "...")
.option("-b, --background-color [name:color]", "Choose a background color.")
.action(console.log)
.parse(Deno.args);
Copy
deno run examples/command/global_custom_type.ts login --color "red"
{ color: "red" }
Copy
Custom types
You can register custom types with the .type()
method. The first argument is
the name of the type, the second can be either a function or an instance of
Type
and the third argument can be an options object.
Function types
This example shows you how to use a function as type handler.
import { ArgumentValue, Command } from "@cliffy/command";
const colors = ["red", "blue", "yellow"];
function colorType({ label, name, value }: ArgumentValue): string {
if (!colors.includes(value.toLowerCase())) {
throw new Error(
`${label} "${name}" must be a valid color, but got "${value}". Possible values are: ${
colors.join(", ")
}`,
);
}
return value;
}
const { options } = await new Command()
.type("color", colorType)
.arguments("[color-name:color]")
.option("-c, --color <name:color>", "...")
.command("foo [color-name:color]", "...")
.parse(Deno.args);
Copy
deno run examples/command/custom_option_type.ts -c "red"
{ color: "red" }
deno run examples/command/custom_option_type.ts -c "green"
Error: Option "--color" must be a valid color, but got "green". Possible values are: red, blue, yellow
Copy
Class types
This example shows you how to create a custom type that extends the base Type
.
import { ArgumentValue, Command, Type, ValidationError } from "@cliffy/command";
class ColorType extends Type<string> {
private readonly colors = ["red", "blue", "yellow"];
public parse({ label, name, value }: ArgumentValue): string {
if (!this.colors.includes(value)) {
throw new ValidationError(
`${label} "${name}" must be a valid color, but got "${value}". Possible values are: ${
this.colors.join(", ")
}`,
);
}
return value;
}
}
const { options } = await new Command()
.type("color", new ColorType())
.arguments("[color-name:color]")
.option("-c, --color <name:color>", "...")
.command("foo [color-name:color]", "...")
.parse(Deno.args);
Copy
deno run examples/command/custom_option_type_class.ts -c "red"
{ color: "red" }
deno run examples/command/custom_option_type_class.ts -c "green"
Error: Option "--color" must be a valid color, but got "green". Possible values are: red, blue, yellow
Copy
The ValidationError
ensures that the help is displayed before the program
exits. You can read more about error handling here.
Shell completions
You can also add shell completions to custom types by adding a complete
method
to your type. Read more about shell completions
here.
import { ArgumentValue, Command, Type } from "@cliffy/command";
class ColorType extends Type<string> {
override complete(): Array<string> {
return ["red", "blue", "yellow"];
}
parse(type: ArgumentValue): string {
return type.value;
}
}
Copy
Override possible values in help text
To override possible values listed in the auto generated help, you can add a
.values()
method to your custom type.
import { ArgumentValue, Command, Type } from "@cliffy/command";
class ColorType extends Type<string> {
override values(): Array<string> {
return ["red", "blue", "yellow"];
}
parse(type: ArgumentValue): string {
return type.value;
}
}
Copy