Size / Priority
- Size: Trivial (~30 lines)
- Category: C.1 Pattern-Matching.
- Risk: low.
Affected files
src/config/HoconParser.ts — value-type dispatch in the value-emitting / substitution-resolving path.
Background
HoconParser produces ConfigValue which is a union:
export type ConfigValue = ConfigPrimitive | ConfigValue[] | ConfigObject | Substitution;
export type ConfigPrimitive = string | number | boolean | null;
Several functions in the parser branch on the value's runtime type:
resolveSubstitutions(value) — recurses through arrays/objects; resolves Substitution leaves.
deepMerge(a, b) — merges objects; replaces primitives.
serialize(value) — emit canonical form.
The dispatch typically uses chained typeof + Array.isArray + isSubstitution checks. ts-pattern's P predicates (P.string, P.number, P.boolean, P.nullish, P.array, P.when) give a uniform syntax.
Target code (example for resolveSubstitutions)
import { match, P } from 'ts-pattern';
import { isSubstitution } from './HoconParser.js';
function resolveSubstitutions(value: ConfigValue, root: ConfigObject): ConfigValue {
return match(value)
.with(P.string, (v) => v)
.with(P.number, (v) => v)
.with(P.boolean, (v) => v)
.with(P.nullish, () => null)
.with(P.array(P.any), (arr) => arr.map(v => resolveSubstitutions(v, root)))
.with({ __substitution: true }, (sub) => resolveOne(sub, root))
.otherwise((obj) => {
// ConfigObject
const out: ConfigObject = {};
for (const [k, v] of Object.entries(obj)) out[k] = resolveSubstitutions(v, root);
return out;
});
}
.otherwise(...) handles the residual ConfigObject case after exhausting primitives, arrays, and substitutions — exhaustiveness preserved via the match's type inference.
Integration / risk
- HOCON parsing semantics unchanged.
- Substitution resolution + deep-merge correctness preserved.
Test plan
- Regression — full HOCON parser test suite.
- Substitution edge cases — nested substitutions, missing keys with
${?optional}.
- Deep-merge tests — multi-source merge order preserved.
Acceptance criteria
Size / Priority
Affected files
src/config/HoconParser.ts— value-type dispatch in the value-emitting / substitution-resolving path.Background
HoconParserproducesConfigValuewhich is a union:Several functions in the parser branch on the value's runtime type:
resolveSubstitutions(value)— recurses through arrays/objects; resolves Substitution leaves.deepMerge(a, b)— merges objects; replaces primitives.serialize(value)— emit canonical form.The dispatch typically uses chained typeof + Array.isArray + isSubstitution checks. ts-pattern's
Ppredicates (P.string,P.number,P.boolean,P.nullish,P.array,P.when) give a uniform syntax.Target code (example for
resolveSubstitutions).otherwise(...)handles the residualConfigObjectcase after exhausting primitives, arrays, and substitutions — exhaustiveness preserved via the match's type inference.Integration / risk
Test plan
${?optional}.Acceptance criteria
match().with(P.*).