Background
Chris floated the idea: "would it make sense in dtsx to have one test against every single ts code?" — there are ~2076 upstream TypeScript diagnostic codes, so the literal reading is a 2,000-test addition.
This issue is a sizing pass on that idea before any code gets written. TL;DR: the axis is good, the count is ~25× too big.
What dtsx already covers
packages/dtsx/test/ already has 30 test files plus 26/22 input/output fixtures, organized by feature group, not by error code:
- Feature:
ts-features.test.ts,generics,class,interface,type,enum,namespace,module,imports,exports,async-generators,branded-types,directives,type-mappings,isolated-declarations - Output safety:
snapshots,output-normalizer,dts,formatter,errors - Perf / infra:
parallel-processor,cache,memory,profiling,fuzzing - Regression:
issue-3093,issue-3095
Coverage by topic is solid. A test-per-TS-code suite is a different axis — exhaustive by error-code identifier rather than by feature group.
The TS code universe
Source: home-lang/home@docs/TS_DIAGNOSTIC_CODE_STATUS.md — Home maintains the canonical generated catalogue (2,076 codes).
| Code range | Count | Relevance to dtsx |
|---|---|---|
| TS9xxx — isolated-declarations / declaration-emit | 34 | Directly relevant. These are the exact failure modes a .d.ts generator has to handle: TS9007 "Function must have explicit return type", TS9013 "Expression type can't be inferred", TS9021 "Extends clause can't contain expression", etc. dtsx's pitch — "infers narrow types from source values without requiring isolatedDeclarations" — is literally solving these. |
| TS1xxx — parser errors | ~90 | Partially relevant. Most are about malformed user source; dtsx doesn't emit them. The useful subset is ~10–15: codes dtsx could accidentally emit in output (TS1005 } expected, TS1009 trailing commas, TS1010 */ expected — same family as the Promise<; breakage stacks' scripts/patch-broken-dts.ts papers over). |
| TS2xxx, TS22xx–TS25xx — type-checker semantic | ~370 | Not relevant. Type-CHECKING failures, not GENERATION concerns. dtsx is upstream of these. |
| TS17xx, TS18xx — modules / JSDoc | ~67 | Mostly not relevant beyond a handful of re-export codes. |
Proposal — three tiers, ~50 tests total
Tier 1 — 34 tests, one per TS9xxx code (highest leverage)
For each TS9xxx code, write a minimal fixture input that would trigger that error under tsc --isolatedDeclarations. Assert:
- dtsx generates a
.d.tswithout crashing. - The output parses cleanly (no TS1xxx syntax errors).
- Re-running
tsc --noEmitover the output does not re-trigger the original TS9xxx code.
Example skeleton for TS9007 (function must have explicit return type):
// input.ts — would error TS9007 under --isolatedDeclarations
export function makeUser(name: string) {
return { name, createdAt: Date.now() }
}
// Assertion against dtsx output:
// 1. produces a .d.ts containing `export function makeUser(name: string): { name: string; createdAt: number; }`
// 2. tsc --noEmit on the .d.ts is clean
// 3. tsc --isolatedDeclarations does not flag TS9007Tier 2 — ~15 output-safety tests (parser-code subset)
Regression tests for parser codes dtsx could emit: TS1005, TS1009, TS1010, TS1011, TS1013, TS1014, TS1015, plus a few more. Tier 2 catches "dtsx wrote syntactically invalid declarations" bugs — exactly the class that scripts/patch-broken-dts.ts had to hand-patch in stacks for bun-query-builder and ts-images.
Tier 3 — optional gap-fill (~0–50 tests)
By TS feature spec, not by error code: mapped types, conditional types, template-literal types, infer, satisfies, decorators, etc. Most of this is already covered by existing files (type-mappings.test.ts, branded-types.test.ts, etc.); Tier 3 is "fill the gaps we don't have yet", not "rewrite from scratch".
Mechanics, if Tier 1 ships
- The TS9xxx list is machine-readable in
home-lang/home@docs/TS_DIAGNOSTIC_CODE_STATUS.mdwith each code's canonical key (e.g.Function_must_have_an_explicit_return_type_annotation_with_isolatedDeclarations_9007). - Small generator script → one stub file per code (
tier1-ts9007.test.ts, …), each pre-populated with the canonical key in the description. - Hand-craft the fixture input per file.
- Re-use existing test infra (
test-utils.ts, the input/output fixture loader,processCode).
Decision points for review
- Scope — Tier 1 only (34 tests, ~1 day) vs Tier 1 + Tier 2 (~50 tests, ~2 days). Tier 3 happens organically as feature gaps are noticed.
- Assertion strictness — byte-exact
.d.tssnapshots vs targetedtoContainchecks vs round-trip-through-tsc-only. - Skip vs include the catalog-only TS9xxx codes — TS9005, TS9006, TS9026 are
catalog-only(Home doesn't reference them yet). Still relevant for dtsx? Probably yes — but worth flagging.
Not starting on this until someone signs off on the scope.
cc: @chrisbreuer