Grilled Cheese

ExploreLog inSign up
Terms of UsePrivacy PolicyCommunity StandardsHelpGet the app

Grilled Cheese is a product of Village Compute

Version devBuilt at: 2026-10-10 01:38:52 EDT

Explore

PostsPeople
LatestRanked
@s0-and-s0.bsky.socialSep 17, 2026, 12:45 AM

NodeJS has a built-in argument parser

Wrapping it with something that can handle type/value mutation is reasonably trivial

And cluing-in TypeScript to mutations makes development a little less annoying, and a little less error prone too :-]

#DevExp #NodeJS #TypeScript

```typescript
/**
 * @file NodeJS builtin argument parsing example with TypeScript enhanced callbacks
 * @author S0AndS0.eth
 * @license This is your problem now (-;
 */

import type { ParseArgsConfig } from "node:util";

import { parseArgs } from "node:util";

type Apply_Callbacks<
	T extends ParseArgsConfig,
	Values = ReturnType<typeof parseArgs<T>>["values"],
	Options = T["options"],
> = {
	[Key in keyof Values]: Options[Key]["callback"] extends Function
		? ReturnType<Options[Key]["callback"]>
		: Values[Key];
};

function parseArguments<T extends ParseArgsConfig>(config?: T) {
	const result = parseArgs(config);

	result.values = Object.entries(result.values).reduce(
		(accumulator, [key, value], _index, array) => {
			const callback = config?.options[key].callback;

			if (callback) {
				accumulator[key] = callback({ value, values: array });
			} else {
				accumulator[key] = value;
			}

			return accumulator;
		},
		{} as Apply_Callbacks<T>
	);

	return result as Omit<ReturnType<typeof parseArgs<T>>, "values"> & {
		values: Apply_Callbacks<T>;
	};
}

const options = {
	verbose: {
		type: "boolean",
		short: "v",
		description: "Output additional information during execution.",
	},
	"as-number": {
		type: "string",
		description:
			"Throws error if given non-number during CLI argument parsing/conversion.",
		callback: ({ value }: { value: string }) => {
			const result = Number(value);
			if (Number.isNaN(result)) {
				throw new Error("Not a number given to: --as-number <value>");
			}
			return result;
		},
	},
} as const;

const { values } = parseArguments({ options });

/* Should now resolve to; number | undefined */
type Test_as_number = (typeof values)["as-number"];

/* Should now resolve to; boolean | undefined */
type Test_verbose = (typeof values)["verbose"];
```
@s0-and-s0.bsky.socialSep 9, 2026, 11:43 PM

So after much fiddling about, and help from another dev, it seems this is the best that can be done in pure TypeScript to expose RegExp constructor(s) and flag(s)

Not happy that it be incomplete, but am satisfied enough that it'll cover most normal use-cases

#devexp #regexp #typescript #webdev

````typescript
/**
 * Thanks to @GucciMAANG for showing `\d` and others are treated as `d`
 */
export type Escape_Entries = {
	'\n': '\\n';
	'\r': '\\r';
	'/': '\\/';
	/* WARNING: Following auto-expand when input, but no easy way to detect here */
	// '\b': '\u0008';
	// '\f': '\u000c';
	// '\v': '\u000b';
	/* WARNING: Following expect two to four more characters, and no easy way to detect here */
	// '\u': '\u0000';
	// '\x': '\u00';
};

/* When uncommented resolves to; "\b \f \v \\u \\x" */
// type Test = Escape_All<'\b \f \v \u \x'>;

export type Maybe_Escape_Character<T extends string>
	= T extends keyof Escape_Entries
	? Escape_Entries[T]
	: T;

export type Escape_All<S extends string>
	= S extends `${infer Head}${infer Tail}`
	? `${Maybe_Escape_Character<Head>}${Escape_All<Tail>}`
	: S;

export type Format_Expression<Type extends string> = `((\\b|\\s)(${Type})(\\b|\\s))`;

export type RegExp_With_Hints<
	Type extends string,
	Flags extends string = '',
	_Formatted = Format_Expression<Escape_All<Type>>,
> = RegExp & {
	source: _Formatted;
	toString(): `/${_Formatted}/${Flags}`;
};

export type Expression_Entries<
	Type extends Record<string, string>,
	Flags extends string = '',
> = {
	[Key in keyof Type]: RegExp_With_Hints<Type[Key], Flags>;
};

const constructors = {
	some_thang_simple: 'some\\s+thang\\s+simple',
	other_thang: 'woot\nnew\rlines?',
} as const;

const flags = 'gi' as const;

export const expressions = Object.entries(constructors).reduce((accumulator, [key, value]) => {
	try {
		const expression = `((\\b|\\s)(${value})(\\b|\\s))`;
		accumulator[key] = new RegExp(expression, flags);
	} catch (error) {
		console.error({ key, value, error });
		throw error;
	}
	return accumulator;
}, {} as Expression_Entries<typeof constructors, typeof flags>) as const;

/* Is; "((\\b|\\s)(woot\\nnew\\rlines?)(\\b|\\s))" */
// expressions.other_thang.source

/* Is; "/((\\b|\\s)(some\\s+thang\\s+simple)(\\b|\\s))/gi" */
// expressions.some_thang_simple.toString()
```
@s0-and-s0.bsky.socialSep 9, 2026, 7:48 PM

One of the definitions I use to figure out if something's Art is if I feel something from it

... I feel things when looking at this TypeScript

#backend #devexp #frontend #typescript #webdev

```typescript
/**
 * Attributions;
 * - https://code.lol/post/programming/higher-kinded-types/
 */

interface HKT {
	_T: unknown;
	result: unknown;
}

type Apply<F extends HKT, T> = (F & { _T: T })['result'];

interface Prepend<T = 'PREPEND '> extends HKT { result: `${T}${this['_T']}`; }
interface Append<T = ' APPEND'> extends HKT { result: `${this['_T']}${T}`; }
interface Sandwich<L, R> extends HKT { result: `${L}${this['_T']}${R}`; }

const value = 'some-thang' as const;
type Value = typeof value;

type Test_Prepend = Apply<Prepend, Value>;
type Test_Append = Apply<Append<' woot?'>, Value>;
type Test_Sandwich = Apply<Sandwich<'Left ', ' Right'>, Value>;
```
@s0-and-s0.bsky.socialSep 8, 2026, 5:34 PM

Likely there are good reasons why this ain't default behavior, however, in this niche use-case I believe type/tab-hints are worth the computational performance hit to reduce cognitive load

#Backend #Frontend #TypeScript #devexp #webdev

`````typescript
type ReplaceAll<
	S extends string,
	From extends string,
	To extends string,
>	= S extends `${infer Head}${From}${infer Tail}`
	? `${Head}${To}${ReplaceAll<Tail, From, To>}`
	: S;

/**
 * What will be given to; `new RegExp`
 */
type Expression_String<T> = `(?<=(<${T}>))(\n.*)*(?=(</${T}>))`;

/**
 * What to expect from; `(new RegExp(...)).toString()`
 */
type Expression_toString<T> = `/${ReplaceAll<
	ReplaceAll<
		Expression_String<T>, '\n', '\\n'>,
		'/',
		'\\/'
>}/`;

/**
 * Put together some type-hint abominations
 */
type Expression_Entries<Type> = {
	[Key in keyof Type]: RegExp & {
		toString: () => Expression_toString<Type[Key]>;
	};
};

const xml_tags = {
	some_thang: "some-thang",
	other_tag: "other-tag",
} as const;

export type XML_Expressions = Expression_Entries<typeof xml_tags>;

export const xml_expressions = Object.entries(xml_tags).reduce(
	(accumulator, [key, value]) => {
		try {
			const expression_string = `(?<=(<${value}>))(\n.*)*(?=(</${value}>))`;
			accumulator[key] = new RegExp(expression_string);
		} catch (error) {
			console.error({ key, value, error });
			throw error;
		}
		return accumulator;
	},
	{} as XML_Expressions
);

/**
 * LSP now will show something like;
 *
 * ```typescript
 * (property) toString: () => "/(?<=(<other-tag>))(\\n.*)*(?=(<\\/other-tag>))/"
 * ```
 */
xml_expressions.other_tag.toString()
`````