Skip to content

test: add tsd type tests for SemVerVersion/SemVerRange assignability - #304

Open
gomesalexandre wants to merge 2 commits into
MetaMask:mainfrom
gomesalexandre:test_semver_types_not_assignable
Open

test: add tsd type tests for SemVerVersion/SemVerRange assignability#304
gomesalexandre wants to merge 2 commits into
MetaMask:mainfrom
gomesalexandre:test_semver_types_not_assignable

Conversation

@gomesalexandre

@gomesalexandregomesalexandre commented Aug 19, 2026

Copy link
Copy Markdown

closes#73

Adds src/versions.test-d.ts, a tsd type-level test proving SemVerVersion and
SemVerRange (opaque/branded string types) aren't mutually assignable to each
other or to a plain string, following the existing .test-d.ts pattern
(hex.test-d.ts, json.test-d.ts, caip-types.test-d.ts, misc.test-d.ts).

Found while verifying: yarn test:types has been a silent no-op repo-wide

Not specific to this new file - every existing .test-d.ts file in the repo is
currently unreachable by yarn test:types. Root cause: tsd's auto-discovery
does typingsFile.replace(/\.d\.ts$/, '.test-d.ts') against package.json's
types field, which is ./dist/index.d.cts - the regex doesn't match .d.cts,
so the fallback to the configured "tsd": {"directory": "src"} glob never fires.
Instead globby matches the literal (post-build) ./dist/index.d.cts path,
finds one file containing zero assertions, and tsd reports a clean pass on
nothing.

One-line repro: append any bogus assertion to an existing *.test-d.ts file
(e.g. expectAssignable<Hex>(12345); in hex.test-d.ts) and yarn test:types
still exits 0.

Fixed in the same PR by pointing the script at the src glob explicitly:
"test:types": "tsd --files 'src/**/*.test-d.ts'". Verified against all 5
existing test-d files (hex, json, caip-types, misc, versions) - clean pass with
the fix, and the bogus-assertion mutation now correctly fails. Zero-risk to CI:
none of the 5 existing files have latent failures the broken discovery was
masking.

Happy to split this into two PRs (test file / script fix) if you'd prefer, but
shipping the test file alone would mean shipping code CI never actually runs, so
I bundled them.

Testing

Mutation-tested the new test file itself: inverted all 6 assertions
(expectAssignable/expectNotAssignable swapped), confirmed tsd catches
every one with a precise brand-mismatch diagnostic, reverted, confirmed clean.
Full jest suite and tsc --noEmit unaffected (7 pre-existing unrelated errors
in node_modules/web3-* typings, confirmed via stash comparison against
unmodified main). eslint clean.


Note

Low Risk
Test-only and script wiring changes with no runtime or public API impact.

Overview
Adds src/versions.test-d.ts so CI checks that SemVerVersion and SemVerRange stay distinct branded strings: values narrowed via assertIsSemVerVersion / assertIsSemVerRange assign to their own types, the two types are not interchangeable, and raw strings are not assignable without those assertions.

Updates test:types from plain tsd to tsd --files 'src/**/*.test-d.ts' because discovery against package.json’s types field (./dist/index.d.cts) never matched .test-d.ts, so type tests (including existing hex, json, etc.) were not actually executed.

Reviewed by Cursor Bugbot for commit d6f39a9. Bugbot is set up for automated code reviews on this repo. Configure here.

closesMetaMask#73
Adds src/versions.test-d.ts, following the existing .test-d.ts pattern
(hex.test-d.ts, json.test-d.ts, caip-types.test-d.ts), proving the two
opaque SemVer types are not mutually assignable at the type level even
though both are strings at runtime, and that a plain string literal
isn't assignable to either without going through its assertion
function first.
yarn test:types (tsd) has been a silent no-op repo-wide since the
package.json types field became ./dist/index.d.cts. tsd 0.29's
auto-discovery does typingsFile.replace(/\.d\.ts$/, '.test-d.ts'),
which doesn't match .d.cts, so the configured tsd.directory: "src"
fallback never fires - instead globby matches the literal ./dist/index.d.cts
path (which exists once CI builds before running test:types), finds
one file with zero assertions in it, and tsd reports a clean pass on
nothing.
Reproduced: appending a bogus assertion to any existing *.test-d.ts
file still exits 0 under the old script. Fixed by pointing tsd at the
src glob explicitly, matching the tsd.directory config's original
intent. Verified against all 5 existing test-d files (hex, json,
caip-types, misc, versions): clean pass with the fix, and the same
bogus-assertion mutation now correctly fails.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add tests for opaque types

1 participant

@gomesalexandre