0
# Flag Parameters
1
2
Type-safe flag definitions supporting boolean, counter, enum, and parsed types with optional, required, and variadic variants.
3
4
## Quick Reference
5
6
```typescript
7
flags: {
8
// Boolean
9
verbose: { kind: "boolean", brief: "Verbose output", default: false },
10
dryRun: { kind: "boolean", brief: "Dry run", optional: true },
11
12
// Counter (repeatable)
13
verbosity: { kind: "counter", brief: "Verbosity level" },
14
15
// Enum (string literals)
16
env: { kind: "enum", values: ["dev", "prod"], brief: "Environment", default: "dev" },
17
18
// Parsed (custom type)
19
port: { kind: "parsed", parse: numberParser, brief: "Port", default: "3000" },
20
timeout: { kind: "parsed", parse: numberParser, brief: "Timeout", optional: true },
21
22
// Variadic
23
files: { kind: "parsed", parse: String, variadic: true, brief: "Files" },
24
tags: { kind: "parsed", parse: String, variadic: ",", brief: "Tags", optional: true }
25
},
26
aliases: { v: "verbose", e: "env", p: "port" }
27
```
28
29
## Flag Types
30
31
### Boolean Flags
32
33
On/off toggles with optional negation syntax.
34
35
```typescript { .api }
36
// Required with default
37
verbose: {
38
kind: "boolean",
39
brief: "Enable verbose output",
40
default: false // optional, defaults to false
41
}
42
43
// Optional
44
dryRun: {
45
kind: "boolean",
46
brief: "Perform dry run",
47
optional: true
48
}
49
```
50
51
**Usage:** `--verbose`, `--no-verbose`, `--dry-run`
52
53
### Counter Flags
54
55
Increment with each occurrence.
56
57
```typescript { .api }
58
verbosity: {
59
kind: "counter",
60
brief: "Increase verbosity (-v, -vv, -vvv)"
61
}
62
```
63
64
**Usage:** `-v` (1), `-vv` (2), `-vvv` (3), `--verbosity --verbosity` (2)
65
66
### Enum Flags
67
68
Predefined set of string values.
69
70
```typescript { .api }
71
// Single value
72
env: {
73
kind: "enum",
74
values: ["dev", "staging", "prod"],
75
brief: "Target environment",
76
default: "dev" // optional
77
}
78
79
// Variadic (multiple values)
80
features: {
81
kind: "enum",
82
values: ["auth", "api", "ui"],
83
brief: "Enabled features",
84
variadic: true // or "," for comma-separated
85
}
86
```
87
88
**Usage:** `--env prod`, `--features auth --features api`, `--features auth,api,ui`
89
90
### Parsed Flags
91
92
Custom parser for any type.
93
94
```typescript { .api }
95
// Single value with default
96
port: {
97
kind: "parsed",
98
parse: numberParser,
99
brief: "Server port",
100
default: "3000"
101
}
102
103
// Optional
104
timeout: {
105
kind: "parsed",
106
parse: (input) => parseInt(input, 10),
107
brief: "Timeout in seconds",
108
optional: true
109
}
110
111
// Variadic
112
files: {
113
kind: "parsed",
114
parse: String,
115
variadic: true,
116
brief: "Input files",
117
proposeCompletions: async () => await readdir(".") // optional
118
}
119
```
120
121
### Flag Properties
122
123
**Common:**
124
- `kind`: "boolean" | "counter" | "enum" | "parsed"
125
- `brief`: string (description)
126
- `optional`: boolean (makes flag optional, undefined if not provided)
127
- `default`: string (for parsed/enum) | boolean (for boolean) - conflicts with optional
128
- `placeholder`: string (custom placeholder in usage line)
129
- `hidden`: boolean (hide from help text)
130
131
**Parsed-specific:**
132
- `parse`: InputParser<T, CONTEXT>
133
- `variadic`: boolean | string (true or separator like ",")
134
- `inferEmpty`: boolean (if flag specified without value, use "")
135
- `proposeCompletions`: (partial: string) => string[] | Promise<string[]>
136
137
**Enum-specific:**
138
- `values`: readonly T[]
139
- `variadic`: boolean | string
140
141
## Type Safety & Type Inference
142
143
### TypedFlagParameter Type
144
145
Generic type for defining flag parameters with full type inference. Automatically infers the appropriate flag type based on TypeScript types.
146
147
```typescript { .api }
148
/**
149
* Definition of a flag parameter
150
* Properties vary based on type T:
151
* - boolean types -> BooleanFlagParameter
152
* - number types -> CounterFlagParameter or ParsedFlagParameter
153
* - string literal unions -> EnumFlagParameter
154
* - arrays -> Variadic flags
155
* - undefined in union -> Optional flags
156
*/
157
type TypedFlagParameter<T, CONTEXT extends CommandContext = CommandContext> =
158
undefined extends T
159
? TypedFlagParameter_Optional<NonNullable<T>, CONTEXT>
160
: TypedFlagParameter_Required<T, CONTEXT>;
161
```
162
163
### FlagParametersForType Type
164
165
Mapped type defining flags for each named parameter in type T. Transforms TypeScript interface into flag parameter definitions.
166
167
```typescript { .api }
168
/**
169
* Definition of flags for each named parameter
170
* Transforms TypeScript interface into flag parameter definitions
171
*/
172
type FlagParametersForType<T, CONTEXT extends CommandContext = CommandContext> = {
173
readonly [K in keyof T]-?: TypedFlagParameter<T[K], CONTEXT>;
174
};
175
```
176
177
**Usage Example:**
178
179
```typescript
180
import { FlagParametersForType, buildCommand } from "@stricli/core";
181
182
// Define flags type
183
interface MyFlags {
184
verbose: boolean;
185
output?: string;
186
count: number;
187
mode: "fast" | "slow";
188
}
189
190
// Type-safe flag parameters
191
const flagParams: FlagParametersForType<MyFlags> = {
192
verbose: {
193
kind: "boolean",
194
brief: "Enable verbose mode"
195
},
196
output: {
197
kind: "parsed",
198
parse: (s) => s,
199
brief: "Output file path",
200
optional: true
201
},
202
count: {
203
kind: "counter",
204
brief: "Repeat count"
205
},
206
mode: {
207
kind: "enum",
208
values: ["fast", "slow"],
209
brief: "Processing mode",
210
default: "fast"
211
}
212
};
213
214
const command = buildCommand({
215
func: async function(flags: MyFlags) {
216
// flags is fully typed!
217
if (flags.verbose) {
218
this.process.stdout.write("Verbose mode\n");
219
}
220
},
221
parameters: {
222
flags: flagParams
223
},
224
docs: {
225
brief: "My command"
226
}
227
});
228
```
229
230
### TypedCommandFlagParameters Type
231
232
Typed definitions for all flag parameters with optional aliases mapping.
233
234
```typescript { .api }
235
/**
236
* Typed definitions for all flag parameters
237
*/
238
interface TypedCommandFlagParameters<
239
FLAGS extends BaseFlags,
240
CONTEXT extends CommandContext
241
> {
242
/** Typed definitions for all flag parameters */
243
readonly flags: FlagParametersForType<FLAGS, CONTEXT>;
244
245
/** Object that aliases single characters to flag names */
246
readonly aliases?: Aliases<keyof FLAGS & string>;
247
}
248
249
/** Root constraint for all flag type parameters */
250
type BaseFlags = Readonly<Record<string, unknown>>;
251
```
252
253
## Aliases
254
255
Object mapping single-character aliases to flag names. Limited to single letters a-g, i-z, A-Z (h is reserved).
256
257
```typescript { .api }
258
/**
259
* Object mapping single-character aliases to flag names
260
* Limited to single letters a-g, i-z, A-Z (h is reserved)
261
*/
262
type Aliases<T> = Readonly<Partial<Record<AvailableAlias, T>>>;
263
264
type AvailableAlias = Exclude<
265
| "a" | "b" | "c" | "d" | "e" | "f" | "g"
266
| "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r"
267
| "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
268
| "A" | "B" | "C" | "D" | "E" | "F" | "G"
269
| "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R"
270
| "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z",
271
"h"
272
>;
273
```
274
275
**Usage Example:**
276
277
```typescript
278
parameters: {
279
flags: { verbose, output, force },
280
aliases: { v: "verbose", o: "output", f: "force" }
281
}
282
283
// Usage: -v -o file.txt -f
284
// Usage: -vof file.txt (combined)
285
// Usage: --verbose --output file.txt --force
286
```
287
288
## Complete Example
289
290
```typescript
291
interface DeployFlags {
292
environment: "dev" | "staging" | "prod";
293
verbose: boolean;
294
dryRun?: boolean;
295
timeout?: number;
296
replicas: number;
297
services: readonly string[];
298
tags?: readonly string[];
299
}
300
301
const deployCommand = buildCommand({
302
func: async function(flags: DeployFlags) {
303
this.process.stdout.write(`Deploying to ${flags.environment}\n`);
304
this.process.stdout.write(`Services: ${flags.services.join(", ")}\n`);
305
if (flags.dryRun) {
306
this.process.stdout.write("DRY RUN\n");
307
return;
308
}
309
},
310
parameters: {
311
flags: {
312
environment: { kind: "enum", values: ["dev", "staging", "prod"], brief: "Environment", default: "dev" },
313
verbose: { kind: "boolean", brief: "Verbose logging", default: false },
314
dryRun: { kind: "boolean", brief: "Dry run mode", optional: true },
315
timeout: { kind: "parsed", parse: numberParser, brief: "Timeout (seconds)", optional: true },
316
replicas: { kind: "counter", brief: "Replicas (specify multiple times)" },
317
services: { kind: "parsed", parse: String, variadic: true, brief: "Services to deploy" },
318
tags: { kind: "parsed", parse: String, variadic: ",", optional: true, brief: "Tags (comma-separated)" }
319
},
320
aliases: { e: "environment", v: "verbose", d: "dryRun", t: "timeout", r: "replicas" }
321
},
322
docs: { brief: "Deploy services" }
323
});
324
325
// Usage:
326
// myapp -e prod -v -rrr --services api --services web
327
// myapp --environment staging --dry-run --timeout 300 --services api
328
// myapp --tags v2.0,stable --services api --services web
329
```
330
331
## Related
332
333
- [Parameter Parsers](./parameter-parsers.md)
334
- [Positional Parameters](./positional-parameters.md)
335