Node's --strip-types does not rewrite import specifiers the way bundlers
and Deno do, so 'import ... from "./match.js"' literally looks for
match.js (not match.ts) and fails with ERR_MODULE_NOT_FOUND at test
time. Fix by switching source imports to .ts extensions and letting
TypeScript's rewriteRelativeImportExtensions do the rewrite at build
emit time.
Changes:
- tsconfig.json: enable allowImportingTsExtensions (works because the
root config has noEmit: true)
- tsconfig.build.json: enable rewriteRelativeImportExtensions so the
emitted dist/*.js files keep './match.js' style imports (correct for
consumers), not './match.ts'
- src/index.ts: import './match.ts' and './pattern.ts'
- src/match.ts: import './pattern.ts'
- src/index.test.ts: import './index.ts'
Verified: npm run test runs tsc --noEmit (passes) and node --test
--strip-types src/ — all 6 tests pass. tsc -p tsconfig.build.json
emits dist/*.js with './match.js' imports as before; consumers see no
change.
Introduce the core builder and pattern constructors:
- match(value): chain .with(pattern, handler) and terminate with
.exhaustive() (throws on no match) or .otherwise(handler).
- P.literal, P.type, P.when, P.any, P.shape for pattern construction.
- Each pattern is a Matcher<T> whose matches acts as a type guard, so
handler parameters are narrowed to the matched type.
The MatchBuilder accumulates handlers and returns a new builder per
.with() call (immutable chaining); finalization runs the cases in order
and returns the first match's handler result.
TypeScript configuration relaxed in .oxlintrc.json:
- Disable eslint/no-undefined (we use undefined as the no-match sentinel)
- Disable eslint/sort-keys (handler order matters; alphabetical would
be wrong)
- Disable eslint/id-length (T/R/U/V generics are standard TS convention)
- Disable import/no-named-export (false positive for library entry points)
Verified:
- tsc --noEmit passes with strict + noUncheckedIndexedAccess
- tsc -p tsconfig.build.json emits dist/*.js + .d.ts + sourcemaps
- node -e "import('./dist/index.js')" loads and exposes { match, P }