Input Types
A Type<Value> converts a raw CLI string into a typed value:
- Contains a
contentlabel about the type of data being decoded - Paired with a
decoderfunction that throws if the value is invalid.
A Type<Value> can then be used as a value for an Option or Positional
Built-in types
All type factories accept an optional name parameter that overrides the label shown in help/errors.
| Type factory | Content type | Accepts |
|---|---|---|
typeString | string | Any string |
typeBoolean | boolean | true/yes/on/y → true, false/no/off/n → false (case-insensitive) |
typeNumber | number | Integers, floats, scientific notation |
typeInteger | bigint | Integer strings only |
typeDatetime | Date | Any format accepted by Date.parse (ISO 8601 recommended) |
typeUrl | URL | Absolute URLs |
typePath | string | Non-empty path strings; optional sync existence check |
typeString("greeting").decoder("hello"); // → "hello"
typeBoolean("flag").decoder("yes"); // → true
typeNumber("pi").decoder("3.14"); // → 3.14
typeInteger("id").decoder("9007199254740993"); // → 9007199254740993n
typeDatetime("birthday").decoder("2024-01-15"); // → Date object
typeUrl("redirect").decoder("https://example.com/path"); // → URL object
typePath().decoder("/usr/bin"); // → "/usr/bin"typePath also accepts a second argument for existence checks:
typePath("config", { checkSyncExistAs: "file" }); // throws if not a file
typePath("dir", { checkSyncExistAs: "directory" }); // throws if not a directorytypeChoice — string enum
Accepts only a fixed set of strings (case-insensitive by default):
const typeEnv = typeChoice("environment", ["dev", "staging", "prod"]);
typeEnv.decoder("prod"); // → "prod"
typeEnv.decoder("PROD"); // → "prod" (case-insensitive)
typeEnv.decoder("unknown"); // Error: Invalid value: "unknown"Pass true as third argument to make matching case-sensitive.
typeTuple — fixed-length delimited value
Splits a string into a fixed-length typed tuple:
const typePoint = typeTuple([typeNumber("a"), typeNumber("b")]);
typePoint.decoder("3.14,2.71"); // → [3.14, 2.71]
typePoint.decoder("x,2"); // → Error: at 0: a: Unable to parse: "x"The default separator is ",". Pass a second argument to change it:
typeTuple([typeString("name"), typeNumber()], ":");
// "foo:42" → ["foo", 42]typeList — variable-length delimited value
Splits a string into an array of typed values:
const typeNumbers = typeList(typeNumber("v"));
typeNumbers.decoder("1,2,3"); // → [1, 2, 3]
typeNumbers.decoder("1,x,3"); // → Error: at 1: v: Unable to parse: "x"Custom separator:
const typePaths = typeList(typePath(), ":");
typePaths.decoder("/usr/bin:/usr/local/bin"); // → ["/usr/bin", "/usr/local/bin"]Prefer
optionRepeatable over typeList when users should pass multiple values as separate flags (--file a --file b rather than --files a,b).
typeMapped — transformed decoded value
Chains a base type with a transformation function:
const typePort = typeMapped("port", typeNumber(), (n) => {
if (n < 1 || n > 65535) {
throw new Error("Out of range");
}
return n;
});
typePort.decoder("8080"); // → 8080
typePort.decoder("99999"); // → Error: Out of rangetypeRenamed — rename a type
Wraps a type with a different label for clearer errors:
const typeUserId = typeRenamed(typeInteger("u64"), "user-id");Custom types
Implement the Type<Value> interface directly:
const typeHexColor: Type<string> = {
content: "hex-color",
decoder(value) {
if (/^#[0-9a-fA-F]{6}$/.test(value)) {
return value;
}
throw new Error(`Not a valid hex color: "${value}"`);
},
};
typeHexColor.decoder("#ff0000"); // → "#ff0000"
typeHexColor.decoder("red"); // → Error: Not a valid hex color: "red"