[READ-ONLY] Mirror of https://github.com/bombshell-dev/args. <1kB CLI flag parser
args args-parser cli command-line command-line-parser node
5

Configure Feed

Select the types of activity you want to include in your feed.

[ci] format

authored by

Nate Moore and committed by
bombshell-bot
(Apr 27, 2025, 2:08 AM UTC) 7040795d bcce162e

+336 -313
+132 -128
src/index.ts
··· 1 1 import type { 2 - Aliases, 3 - Args, 4 - BooleanType, 5 - Collectable, 6 - NestedMapping, 7 - ParseOptions, 8 - StringType, 9 - Values, 2 + Aliases, 3 + Args, 4 + BooleanType, 5 + Collectable, 6 + NestedMapping, 7 + ParseOptions, 8 + StringType, 9 + Values, 10 10 } from "./types.js"; 11 11 export { ParseOptions, Args } from "./types.js"; 12 12 ··· 14 14 const QUOTED_RE = /^('|").*\1$/; 15 15 16 16 const set = (obj: NestedMapping, key: string, value: any, type?: string) => { 17 - if (key.includes(".")) { 18 - const parts = key.split("."); 19 - for (let i = 0; i < parts.length - 1; i++) { 20 - const k = parts[i]; 21 - const tmp = {}; 22 - set(obj, k, tmp); 23 - obj = tmp; 24 - } 25 - key = parts[parts.length - 1]; 26 - } 27 - if (type === "array" && obj[key] !== undefined) { 28 - if (Array.isArray(obj[key])) { 29 - (obj[key] as any[]).push(value); 30 - } else { 31 - obj[key] = [obj[key], value]; 32 - } 33 - } else { 34 - obj[key] = type === "array" ? [value] : value; 35 - } 17 + if (key.includes(".")) { 18 + const parts = key.split("."); 19 + for (let i = 0; i < parts.length - 1; i++) { 20 + const k = parts[i]; 21 + const tmp = {}; 22 + set(obj, k, tmp); 23 + obj = tmp; 24 + } 25 + key = parts[parts.length - 1]; 26 + } 27 + if (type === "array" && obj[key] !== undefined) { 28 + if (Array.isArray(obj[key])) { 29 + (obj[key] as any[]).push(value); 30 + } else { 31 + obj[key] = [obj[key], value]; 32 + } 33 + } else { 34 + obj[key] = type === "array" ? [value] : value; 35 + } 36 36 }; 37 37 38 38 const type = ( 39 - key: string, 40 - opts: Record<"boolean" | "string" | "array", string[]> 39 + key: string, 40 + opts: Record<"boolean" | "string" | "array", string[]>, 41 41 ): "boolean" | "string" | "array" | undefined => { 42 - if (opts.array && opts.array.length > 0 && opts.array.includes(key)) 43 - return "array"; 44 - if (opts.string && opts.string.length > 0 && opts.string.includes(key)) 45 - return "string"; 46 - if (opts.boolean && opts.boolean.length > 0 && opts.boolean.includes(key)) 47 - return "boolean"; 48 - return; 42 + if (opts.array && opts.array.length > 0 && opts.array.includes(key)) 43 + return "array"; 44 + if (opts.string && opts.string.length > 0 && opts.string.includes(key)) 45 + return "string"; 46 + if (opts.boolean && opts.boolean.length > 0 && opts.boolean.includes(key)) 47 + return "boolean"; 48 + return; 49 49 }; 50 50 51 51 const defaultValue = (type?: "boolean" | "string" | "array") => { 52 - if (type === "string") return ""; 53 - if (type === "array") return []; 54 - return true; 52 + if (type === "string") return ""; 53 + if (type === "array") return []; 54 + return true; 55 55 }; 56 56 57 57 const coerce = (value?: string, type?: "string" | "boolean" | "array") => { 58 - if (type === "string") return value; 59 - if (type === "boolean") return value === undefined ? true : value === 'true'; 58 + if (type === "string") return value; 59 + if (type === "boolean") return value === undefined ? true : value === "true"; 60 60 61 - if (!value) return value; 62 - if (value.length > 3 && BOOL_RE.test(value)) return value === "true"; 63 - if (value.length > 2 && QUOTED_RE.test(value)) return value.slice(1, -1); 64 - if (value[0] === '.' && /\d/.test(value[1]) || /\d/.test(value[0])) return Number(value); 65 - return value; 61 + if (!value) return value; 62 + if (value.length > 3 && BOOL_RE.test(value)) return value === "true"; 63 + if (value.length > 2 && QUOTED_RE.test(value)) return value.slice(1, -1); 64 + if ((value[0] === "." && /\d/.test(value[1])) || /\d/.test(value[0])) 65 + return Number(value); 66 + return value; 66 67 }; 67 68 68 69 export function parse< 69 - TArgs extends Values< 70 - TBooleans, 71 - TStrings, 72 - TCollectable, 73 - undefined, 74 - TDefaults, 75 - TAliases 76 - >, 77 - TBooleans extends BooleanType = undefined, 78 - TStrings extends StringType = undefined, 79 - TCollectable extends Collectable = undefined, 80 - TDefaults extends Record<string, unknown> | undefined = undefined, 81 - TAliases extends Aliases<TAliasArgNames, TAliasNames> | undefined = undefined, 82 - TAliasArgNames extends string = string, 83 - TAliasNames extends string = string 70 + TArgs extends Values< 71 + TBooleans, 72 + TStrings, 73 + TCollectable, 74 + undefined, 75 + TDefaults, 76 + TAliases 77 + >, 78 + TBooleans extends BooleanType = undefined, 79 + TStrings extends StringType = undefined, 80 + TCollectable extends Collectable = undefined, 81 + TDefaults extends Record<string, unknown> | undefined = undefined, 82 + TAliases extends Aliases<TAliasArgNames, TAliasNames> | undefined = undefined, 83 + TAliasArgNames extends string = string, 84 + TAliasNames extends string = string, 84 85 >( 85 - argv: string[], 86 - { 87 - default: defaults, 88 - alias: aliases, 89 - ...types 90 - }: ParseOptions<TBooleans, TStrings, TCollectable, TDefaults, TAliases> = {} 86 + argv: string[], 87 + { 88 + default: defaults, 89 + alias: aliases, 90 + ...types 91 + }: ParseOptions<TBooleans, TStrings, TCollectable, TDefaults, TAliases> = {}, 91 92 ): Args<TArgs> { 92 - const obj = { ...defaults, _: [] } as unknown as Args<TArgs>; 93 - if (argv.length === 0) return obj; 93 + const obj = { ...defaults, _: [] } as unknown as Args<TArgs>; 94 + if (argv.length === 0) return obj; 94 95 95 - for (let i = 0; i < argv.length; i++) { 96 - const curr = argv[i]; 97 - const next = argv[i + 1]; 96 + for (let i = 0; i < argv.length; i++) { 97 + const curr = argv[i]; 98 + const next = argv[i + 1]; 98 99 99 - let t: 'string' | 'boolean' | 'array' | undefined; 100 - let key = ''; 101 - let value: string | undefined; 100 + let t: "string" | "boolean" | "array" | undefined; 101 + let key = ""; 102 + let value: string | undefined; 102 103 103 - if (curr.length > 1 && curr[0] === "-") { 104 - if (curr[1] !== "-" && curr.length > 2 && !curr.includes('=')) { 105 - if (curr.includes('.')) { 106 - key = curr.slice(1, 2); 107 - value = curr.slice(2); 108 - } else { 109 - const keys = curr.slice(1, -1); 110 - for (let key of keys) { 111 - if (aliases && (aliases as Record<string, any>)[key] !== undefined) { 112 - key = aliases[key as keyof typeof aliases] as string; 113 - } 114 - set(obj, key, defaultValue(t), t) 115 - } 116 - key = curr.slice(-1) 117 - if (next && next[0] !== '-') { 118 - value = next; 119 - i++; 120 - } 121 - } 122 - } else if (!curr.includes("=") && next && next[0] !== "-") { 123 - key = curr.replace(/^-{1,2}/, ''); 124 - t = type(key, types as any); 125 - // treat boolean as flag without parameter 126 - if (t === 'boolean') { 127 - value = 'true'; 128 - } else { 129 - value = next; 130 - i++; 131 - } 132 - } else { 133 - const eq = curr.indexOf('='); 134 - if (eq === -1) { 135 - key = curr.replace(/^-{1,2}/, ''); 136 - } else { 137 - key = curr.slice(0, eq).replace(/^-{1,2}/, ''); 138 - value = curr.slice(eq + 1); 139 - } 140 - t = type(key, types as any); 141 - } 104 + if (curr.length > 1 && curr[0] === "-") { 105 + if (curr[1] !== "-" && curr.length > 2 && !curr.includes("=")) { 106 + if (curr.includes(".")) { 107 + key = curr.slice(1, 2); 108 + value = curr.slice(2); 109 + } else { 110 + const keys = curr.slice(1, -1); 111 + for (let key of keys) { 112 + if ( 113 + aliases && 114 + (aliases as Record<string, any>)[key] !== undefined 115 + ) { 116 + key = aliases[key as keyof typeof aliases] as string; 117 + } 118 + set(obj, key, defaultValue(t), t); 119 + } 120 + key = curr.slice(-1); 121 + if (next && next[0] !== "-") { 122 + value = next; 123 + i++; 124 + } 125 + } 126 + } else if (!curr.includes("=") && next && next[0] !== "-") { 127 + key = curr.replace(/^-{1,2}/, ""); 128 + t = type(key, types as any); 129 + // treat boolean as flag without parameter 130 + if (t === "boolean") { 131 + value = "true"; 132 + } else { 133 + value = next; 134 + i++; 135 + } 136 + } else { 137 + const eq = curr.indexOf("="); 138 + if (eq === -1) { 139 + key = curr.replace(/^-{1,2}/, ""); 140 + } else { 141 + key = curr.slice(0, eq).replace(/^-{1,2}/, ""); 142 + value = curr.slice(eq + 1); 143 + } 144 + t = type(key, types as any); 145 + } 142 146 143 - if ((!t || t === "boolean") && key.length > 3 && key.startsWith('no-')) { 144 - set(obj, key.slice(3), false) 145 - } else { 146 - if (aliases && (aliases as Record<string, any>)[key] !== undefined) { 147 - key = aliases[key as keyof typeof aliases] as string; 148 - } 149 - set(obj, key, coerce(value, t) ?? defaultValue(t), t) 150 - } 151 - } else if (curr) { 152 - (obj as any)._.push(coerce(curr)); 153 - continue; 154 - } 155 - } 147 + if ((!t || t === "boolean") && key.length > 3 && key.startsWith("no-")) { 148 + set(obj, key.slice(3), false); 149 + } else { 150 + if (aliases && (aliases as Record<string, any>)[key] !== undefined) { 151 + key = aliases[key as keyof typeof aliases] as string; 152 + } 153 + set(obj, key, coerce(value, t) ?? defaultValue(t), t); 154 + } 155 + } else if (curr) { 156 + (obj as any)._.push(coerce(curr)); 157 + continue; 158 + } 159 + } 156 160 157 - return obj; 161 + return obj; 158 162 }
+204 -185
src/types.ts
··· 1 1 /** Combines recursively all intersection types and returns a new single type. */ 2 2 type Id<TRecord> = TRecord extends Record<string, unknown> 3 - ? TRecord extends infer InferredRecord 4 - ? { [Key in keyof InferredRecord]: Id<InferredRecord[Key]> } 5 - : never 6 - : TRecord; 3 + ? TRecord extends infer InferredRecord 4 + ? { [Key in keyof InferredRecord]: Id<InferredRecord[Key]> } 5 + : never 6 + : TRecord; 7 7 8 8 /** Converts a union type `A | B | C` into an intersection type `A & B & C`. */ 9 - type UnionToIntersection<TValue> = 10 - (TValue extends unknown ? (args: TValue) => unknown : never) extends 11 - (args: infer R) => unknown ? R extends Record<string, unknown> ? R : never 12 - : never; 9 + type UnionToIntersection<TValue> = ( 10 + TValue extends unknown 11 + ? (args: TValue) => unknown 12 + : never 13 + ) extends (args: infer R) => unknown 14 + ? R extends Record<string, unknown> 15 + ? R 16 + : never 17 + : never; 13 18 14 19 export type BooleanType = boolean | string | undefined; 15 20 export type StringType = string | undefined; ··· 19 24 export type Negatable = string | undefined; 20 25 21 26 type UseTypes< 22 - TBooleans extends BooleanType, 23 - TStrings extends StringType, 24 - TCollectable extends Collectable, 25 - > = undefined extends ( 26 - & (false extends TBooleans ? undefined : TBooleans) 27 - & TCollectable 28 - & TStrings 29 - ) ? false 30 - : true; 27 + TBooleans extends BooleanType, 28 + TStrings extends StringType, 29 + TCollectable extends Collectable, 30 + > = undefined extends (false extends TBooleans ? undefined : TBooleans) & 31 + TCollectable & 32 + TStrings 33 + ? false 34 + : true; 31 35 32 36 /** 33 37 * Creates a record with all available flags with the corresponding type and 34 38 * default type. 35 39 */ 36 40 export type Values< 37 - TBooleans extends BooleanType, 38 - TStrings extends StringType, 39 - TCollectable extends Collectable, 40 - TNegatable extends Negatable, 41 - TDefault extends Record<string, unknown> | undefined, 42 - TAliases extends Aliases | undefined, 43 - > = UseTypes<TBooleans, TStrings, TCollectable> extends true ? 44 - & Record<string, unknown> 45 - & AddAliases< 46 - SpreadDefaults< 47 - & CollectValues<TStrings, string, TCollectable, TNegatable> 48 - & RecursiveRequired<CollectValues<TBooleans, boolean, TCollectable>> 49 - & CollectUnknownValues< 50 - TBooleans, 51 - TStrings, 52 - TCollectable, 53 - TNegatable 54 - >, 55 - DedotRecord<TDefault> 56 - >, 57 - TAliases 58 - > 59 - // deno-lint-ignore no-explicit-any 60 - : Record<string, any>; 41 + TBooleans extends BooleanType, 42 + TStrings extends StringType, 43 + TCollectable extends Collectable, 44 + TNegatable extends Negatable, 45 + TDefault extends Record<string, unknown> | undefined, 46 + TAliases extends Aliases | undefined, 47 + > = UseTypes<TBooleans, TStrings, TCollectable> extends true 48 + ? Record<string, unknown> & 49 + AddAliases< 50 + SpreadDefaults< 51 + CollectValues<TStrings, string, TCollectable, TNegatable> & 52 + RecursiveRequired<CollectValues<TBooleans, boolean, TCollectable>> & 53 + CollectUnknownValues<TBooleans, TStrings, TCollectable, TNegatable>, 54 + DedotRecord<TDefault> 55 + >, 56 + TAliases 57 + > 58 + : // deno-lint-ignore no-explicit-any 59 + Record<string, any>; 61 60 62 - export type Aliases<TArgNames = string, TAliasNames extends string = string> = Partial< 63 - Record<Extract<TArgNames, string>, TAliasNames | ReadonlyArray<TAliasNames>> 61 + export type Aliases< 62 + TArgNames = string, 63 + TAliasNames extends string = string, 64 + > = Partial< 65 + Record<Extract<TArgNames, string>, TAliasNames | ReadonlyArray<TAliasNames>> 64 66 >; 65 67 66 - type AddAliases< 67 - TArgs, 68 - TAliases extends Aliases | undefined, 69 - > = { 70 - [TArgName in keyof TArgs as AliasNames<TArgName, TAliases>]: TArgs[TArgName]; 68 + type AddAliases<TArgs, TAliases extends Aliases | undefined> = { 69 + [TArgName in keyof TArgs as AliasNames<TArgName, TAliases>]: TArgs[TArgName]; 71 70 }; 72 71 73 72 type AliasNames< 74 - TArgName, 75 - TAliases extends Aliases | undefined, 73 + TArgName, 74 + TAliases extends Aliases | undefined, 76 75 > = TArgName extends keyof TAliases 77 - ? string extends TAliases[TArgName] ? TArgName 78 - : TAliases[TArgName] extends string ? TArgName | TAliases[TArgName] 79 - : TAliases[TArgName] extends Array<string> 80 - ? TArgName | TAliases[TArgName][number] 81 - : TArgName 82 - : TArgName; 76 + ? string extends TAliases[TArgName] 77 + ? TArgName 78 + : TAliases[TArgName] extends string 79 + ? TArgName | TAliases[TArgName] 80 + : TAliases[TArgName] extends Array<string> 81 + ? TArgName | TAliases[TArgName][number] 82 + : TArgName 83 + : TArgName; 83 84 84 85 /** 85 86 * Spreads all default values of Record `TDefaults` into Record `TArgs` ··· 90 91 * 91 92 * **Result:** `{ foo: boolean | number, bar?: number }` 92 93 */ 93 - type SpreadDefaults<TArgs, TDefaults> = TDefaults extends undefined ? TArgs 94 - : TArgs extends Record<string, unknown> ? 95 - & Omit<TArgs, keyof TDefaults> 96 - & { 97 - [Default in keyof TDefaults]: Default extends keyof TArgs 98 - ? (TArgs[Default] & TDefaults[Default] | TDefaults[Default]) extends 99 - Record<string, unknown> 100 - ? NonNullable<SpreadDefaults<TArgs[Default], TDefaults[Default]>> 101 - : TDefaults[Default] | NonNullable<TArgs[Default]> 102 - : unknown; 103 - } 104 - : never; 94 + type SpreadDefaults<TArgs, TDefaults> = TDefaults extends undefined 95 + ? TArgs 96 + : TArgs extends Record<string, unknown> 97 + ? Omit<TArgs, keyof TDefaults> & { 98 + [Default in keyof TDefaults]: Default extends keyof TArgs 99 + ? 100 + | (TArgs[Default] & TDefaults[Default]) 101 + | TDefaults[Default] extends Record<string, unknown> 102 + ? NonNullable<SpreadDefaults<TArgs[Default], TDefaults[Default]>> 103 + : TDefaults[Default] | NonNullable<TArgs[Default]> 104 + : unknown; 105 + } 106 + : never; 105 107 106 108 /** 107 109 * Defines the Record for the `default` option to add 108 110 * auto-suggestion support for IDE's. 109 111 */ 110 112 type Defaults<TBooleans extends BooleanType, TStrings extends StringType> = Id< 111 - UnionToIntersection< 112 - & Record<string, unknown> 113 - // Dedotted auto suggestions: { foo: { bar: unknown } } 114 - & MapTypes<TStrings, unknown> 115 - & MapTypes<TBooleans, unknown> 116 - // Flat auto suggestions: { "foo.bar": unknown } 117 - & MapDefaults<TBooleans> 118 - & MapDefaults<TStrings> 119 - > 113 + UnionToIntersection< 114 + Record<string, unknown> & 115 + // Dedotted auto suggestions: { foo: { bar: unknown } } 116 + MapTypes<TStrings, unknown> & 117 + MapTypes<TBooleans, unknown> & 118 + // Flat auto suggestions: { "foo.bar": unknown } 119 + MapDefaults<TBooleans> & 120 + MapDefaults<TStrings> 121 + > 120 122 >; 121 123 122 124 type MapDefaults<TArgNames extends ArgType> = Partial< 123 - Record<TArgNames extends string ? TArgNames : string, unknown> 125 + Record<TArgNames extends string ? TArgNames : string, unknown> 124 126 >; 125 127 126 - type RecursiveRequired<TRecord> = TRecord extends Record<string, unknown> ? { 127 - [Key in keyof TRecord]-?: RecursiveRequired<TRecord[Key]>; 128 - } 129 - : TRecord; 128 + type RecursiveRequired<TRecord> = TRecord extends Record<string, unknown> 129 + ? { 130 + [Key in keyof TRecord]-?: RecursiveRequired<TRecord[Key]>; 131 + } 132 + : TRecord; 130 133 131 134 /** Same as `MapTypes` but also supports collectable options. */ 132 135 type CollectValues< 133 - TArgNames extends ArgType, 134 - TType, 135 - TCollectable extends Collectable, 136 - TNegatable extends Negatable = undefined, 136 + TArgNames extends ArgType, 137 + TType, 138 + TCollectable extends Collectable, 139 + TNegatable extends Negatable = undefined, 137 140 > = UnionToIntersection< 138 - Extract<TArgNames, TCollectable> extends string ? 139 - & (Exclude<TArgNames, TCollectable> extends never ? Record<never, never> 140 - : MapTypes<Exclude<TArgNames, TCollectable>, TType, TNegatable>) 141 - & (Extract<TArgNames, TCollectable> extends never ? Record<never, never> 142 - : RecursiveRequired< 143 - MapTypes<Extract<TArgNames, TCollectable>, Array<TType>, TNegatable> 144 - >) 145 - : MapTypes<TArgNames, TType, TNegatable> 141 + Extract<TArgNames, TCollectable> extends string 142 + ? (Exclude<TArgNames, TCollectable> extends never 143 + ? Record<never, never> 144 + : MapTypes<Exclude<TArgNames, TCollectable>, TType, TNegatable>) & 145 + (Extract<TArgNames, TCollectable> extends never 146 + ? Record<never, never> 147 + : RecursiveRequired< 148 + MapTypes< 149 + Extract<TArgNames, TCollectable>, 150 + Array<TType>, 151 + TNegatable 152 + > 153 + >) 154 + : MapTypes<TArgNames, TType, TNegatable> 146 155 >; 147 156 148 157 /** Same as `Record` but also supports dotted and negatable options. */ 149 158 type MapTypes< 150 - TArgNames extends ArgType, 151 - TType, 152 - TNegatable extends Negatable = undefined, 153 - > = undefined extends TArgNames ? Record<never, never> 154 - : TArgNames extends `${infer Name}.${infer Rest}` ? { 155 - [Key in Name]?: MapTypes< 156 - Rest, 157 - TType, 158 - TNegatable extends `${Name}.${infer Negate}` ? Negate : undefined 159 - >; 160 - } 161 - : TArgNames extends string ? Partial< 162 - Record<TArgNames, TNegatable extends TArgNames ? TType | false : TType> 163 - > 164 - : Record<never, never>; 159 + TArgNames extends ArgType, 160 + TType, 161 + TNegatable extends Negatable = undefined, 162 + > = undefined extends TArgNames 163 + ? Record<never, never> 164 + : TArgNames extends `${infer Name}.${infer Rest}` 165 + ? { 166 + [Key in Name]?: MapTypes< 167 + Rest, 168 + TType, 169 + TNegatable extends `${Name}.${infer Negate}` ? Negate : undefined 170 + >; 171 + } 172 + : TArgNames extends string 173 + ? Partial< 174 + Record< 175 + TArgNames, 176 + TNegatable extends TArgNames ? TType | false : TType 177 + > 178 + > 179 + : Record<never, never>; 165 180 166 181 type CollectUnknownValues< 167 - TBooleans extends BooleanType, 168 - TStrings extends StringType, 169 - TCollectable extends Collectable, 170 - TNegatable extends Negatable, 182 + TBooleans extends BooleanType, 183 + TStrings extends StringType, 184 + TCollectable extends Collectable, 185 + TNegatable extends Negatable, 171 186 > = UnionToIntersection< 172 - TCollectable extends TBooleans & TStrings ? Record<never, never> 173 - : DedotRecord< 174 - // Unknown collectable & non-negatable args. 175 - & Record< 176 - Exclude< 177 - Extract<Exclude<TCollectable, TNegatable>, string>, 178 - Extract<TStrings | TBooleans, string> 179 - >, 180 - Array<unknown> 181 - > 182 - // Unknown collectable & negatable args. 183 - & Record< 184 - Exclude< 185 - Extract<Extract<TCollectable, TNegatable>, string>, 186 - Extract<TStrings | TBooleans, string> 187 - >, 188 - Array<unknown> | false 189 - > 190 - > 187 + TCollectable extends TBooleans & TStrings 188 + ? Record<never, never> 189 + : DedotRecord< 190 + // Unknown collectable & non-negatable args. 191 + Record< 192 + Exclude< 193 + Extract<Exclude<TCollectable, TNegatable>, string>, 194 + Extract<TStrings | TBooleans, string> 195 + >, 196 + Array<unknown> 197 + > & 198 + // Unknown collectable & negatable args. 199 + Record< 200 + Exclude< 201 + Extract<Extract<TCollectable, TNegatable>, string>, 202 + Extract<TStrings | TBooleans, string> 203 + >, 204 + Array<unknown> | false 205 + > 206 + > 191 207 >; 192 208 193 209 /** Converts `{ "foo.bar.baz": unknown }` into `{ foo: { bar: { baz: unknown } } }`. */ 194 - type DedotRecord<TRecord> = Record<string, unknown> extends TRecord ? TRecord 195 - : TRecord extends Record<string, unknown> ? UnionToIntersection< 196 - ValueOf< 197 - { 198 - [Key in keyof TRecord]: Key extends string ? Dedot<Key, TRecord[Key]> 199 - : never; 200 - } 201 - > 202 - > 203 - : TRecord; 210 + type DedotRecord<TRecord> = Record<string, unknown> extends TRecord 211 + ? TRecord 212 + : TRecord extends Record<string, unknown> 213 + ? UnionToIntersection< 214 + ValueOf<{ 215 + [Key in keyof TRecord]: Key extends string 216 + ? Dedot<Key, TRecord[Key]> 217 + : never; 218 + }> 219 + > 220 + : TRecord; 204 221 205 - type Dedot<TKey extends string, TValue> = TKey extends 206 - `${infer Name}.${infer Rest}` ? { [Key in Name]: Dedot<Rest, TValue> } 207 - : { [Key in TKey]: TValue }; 222 + type Dedot< 223 + TKey extends string, 224 + TValue, 225 + > = TKey extends `${infer Name}.${infer Rest}` 226 + ? { [Key in Name]: Dedot<Rest, TValue> } 227 + : { [Key in TKey]: TValue }; 208 228 209 229 type ValueOf<TValue> = TValue[keyof TValue]; 210 230 211 231 /** The value returned from `parse`. */ 212 232 export type Args< 213 - // deno-lint-ignore no-explicit-any 214 - TArgs extends Record<string, unknown> = Record<string, any> 233 + // deno-lint-ignore no-explicit-any 234 + TArgs extends Record<string, unknown> = Record<string, any>, 215 235 > = Id< 216 - & TArgs 217 - & { 218 - /** Contains all the arguments that didn't have an option associated with 219 - * them. */ 220 - _: Array<string | number | boolean>; 221 - } 236 + TArgs & { 237 + /** Contains all the arguments that didn't have an option associated with 238 + * them. */ 239 + _: Array<string | number | boolean>; 240 + } 222 241 >; 223 242 224 243 /** The options for the `parse` call. */ 225 244 export interface ParseOptions< 226 - TBooleans extends BooleanType = BooleanType, 227 - TStrings extends StringType = StringType, 228 - TCollectable extends Collectable = Collectable, 229 - TDefault extends Record<string, unknown> | undefined = 230 - | Record<string, unknown> 231 - | undefined, 232 - TAliases extends Aliases | undefined = Aliases | undefined, 245 + TBooleans extends BooleanType = BooleanType, 246 + TStrings extends StringType = StringType, 247 + TCollectable extends Collectable = Collectable, 248 + TDefault extends Record<string, unknown> | undefined = 249 + | Record<string, unknown> 250 + | undefined, 251 + TAliases extends Aliases | undefined = Aliases | undefined, 233 252 > { 234 - /** 235 - * An object mapping string names to strings or arrays of string argument 236 - * names to use as aliases. 237 - */ 238 - alias?: TAliases; 253 + /** 254 + * An object mapping string names to strings or arrays of string argument 255 + * names to use as aliases. 256 + */ 257 + alias?: TAliases; 239 258 240 - /** 241 - * A boolean, string or array of strings to always treat as booleans. If 242 - * `true` will treat all double hyphenated arguments without equal signs as 243 - * `boolean` (e.g. affects `--foo`, not `-f` or `--foo=bar`). 244 - * All `boolean` arguments will be set to `false` by default. 245 - */ 246 - boolean?: TBooleans | ReadonlyArray<Extract<TBooleans, string>>; 259 + /** 260 + * A boolean, string or array of strings to always treat as booleans. If 261 + * `true` will treat all double hyphenated arguments without equal signs as 262 + * `boolean` (e.g. affects `--foo`, not `-f` or `--foo=bar`). 263 + * All `boolean` arguments will be set to `false` by default. 264 + */ 265 + boolean?: TBooleans | ReadonlyArray<Extract<TBooleans, string>>; 247 266 248 - /** An object mapping string argument names to default values. */ 249 - default?: TDefault & Defaults<TBooleans, TStrings>; 267 + /** An object mapping string argument names to default values. */ 268 + default?: TDefault & Defaults<TBooleans, TStrings>; 250 269 251 - /** A string or array of strings argument names to always treat as strings. */ 252 - string?: TStrings | ReadonlyArray<Extract<TStrings, string>>; 270 + /** A string or array of strings argument names to always treat as strings. */ 271 + string?: TStrings | ReadonlyArray<Extract<TStrings, string>>; 253 272 254 - /** 255 - * A string or array of strings argument names to always treat as arrays. 256 - * Array options can be used multiple times. All values will be 257 - * collected into one array. If a non-array option is used multiple 258 - * times, the last value is used. 259 - * All Collectable arguments will be set to `[]` by default. 260 - */ 261 - array?: TCollectable | ReadonlyArray<Extract<TCollectable, string>>; 273 + /** 274 + * A string or array of strings argument names to always treat as arrays. 275 + * Array options can be used multiple times. All values will be 276 + * collected into one array. If a non-array option is used multiple 277 + * times, the last value is used. 278 + * All Collectable arguments will be set to `[]` by default. 279 + */ 280 + array?: TCollectable | ReadonlyArray<Extract<TCollectable, string>>; 262 281 } 263 282 264 283 export interface NestedMapping { 265 - [key: string]: NestedMapping | unknown; 284 + [key: string]: NestedMapping | unknown; 266 285 }