{"_id":"@diegogbrisa/ts-match","_rev":"12-904aece490faab433d61db597d26f99d","name":"@diegogbrisa/ts-match","dist-tags":{"latest":"1.6.2"},"versions":{"1.0.0":{"name":"@diegogbrisa/ts-match","version":"1.0.0","keywords":["typescript","pattern-matching","exhaustive","match","discriminated-unions"],"license":"MIT","_id":"@diegogbrisa/ts-match@1.0.0","maintainers":[{"name":"diegogbrisa","email":"d.garciabrisa@gmail.com"}],"dist":{"shasum":"e60978658791a8b879a491c6a7e870fb2a86dcbe","tarball":"https://registry.npmjs.org/@diegogbrisa/ts-match/-/ts-match-1.0.0.tgz","fileCount":49,"integrity":"sha512-9/MtgMuEsGqyQZtAt5AustMLoJYaoVlYmHBo2VRelm/OIF9Qsdadd2tQXqsJKhXUTGHW3Vrje5+2ftk9K/YSTA==","signatures":[{"sig":"MEQCIA/aSA1I2PhvhSub/CpJwtjzo4atqziUb+7mCpow5zE/AiB0ZCkVik+lB/xrZrGsafEcNTQ5CdnznOICFU7YPaVA5w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":220449},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./group":{"types":"./dist/group.d.ts","import":"./dist/group.js"},"./match":{"types":"./dist/match.d.ts","import":"./dist/match.js"},"./errors":{"types":"./dist/errors.d.ts","import":"./dist/errors.js"},"./match-by":{"types":"./dist/match-by.d.ts","import":"./dist/match-by.js"},"./patterns":{"types":"./dist/patterns.d.ts","import":"./dist/patterns.js"},"./assertions":{"types":"./dist/assertions.d.ts","import":"./dist/assertions.js"}},"gitHead":"adb7340197be0735cb607cd8e63d9fef91a408a7","scripts":{"lint":"eslint \"**/*.ts\"","test":"vitest run","build":"pnpm clean && tsc -p tsconfig.build.json","check":"pnpm lint && pnpm format:check && pnpm typecheck && pnpm test:type && pnpm test:diagnostics && pnpm test:coverage && pnpm build && pnpm smoke:exports && pnpm test:docs && pnpm test:examples:validate && pnpm test:examples:run","clean":"rm -rf dist","format":"prettier . --write","lint:fix":"eslint \"**/*.ts\" --fix","test:docs":"tsx scripts/validate-docs.ts","test:type":"tsc -p tsconfig.type-tests.json --noEmit","typecheck":"pnpm build && tsc -p tsconfig.json --noEmit","pack:check":"rm -rf .pack && mkdir -p .pack && pnpm build && pnpm pack --pack-destination .pack --json && pnpm check:package-contents && tsx scripts/smoke-tarball.ts","bench:types":"tsc -p tsconfig.type-bench.json --noEmit --extendedDiagnostics","bench:native":"pnpm build && tsx benchmarks/native.ts","format:check":"prettier . --check","bench:compare":"pnpm build && tsx benchmarks/compare-ts-pattern.ts","check:commits":"tsx scripts/check-conventional-commits.ts","release:notes":"tsx scripts/extract-release-notes.ts","smoke:exports":"tsx scripts/smoke-exports.ts","test:coverage":"vitest run --coverage","test:examples":"pnpm build && pnpm test:examples:validate && pnpm test:examples:run","bench:dispatch":"tsx benchmarks/dispatch.ts","prepublishOnly":"pnpm release:preflight","typecheck:types":"pnpm test:type","test:diagnostics":"tsx scripts/check-diagnostics.ts","release:preflight":"pnpm check && pnpm bench:types && pnpm bench:native:check && pnpm pack:check && pnpm audit --prod && pnpm check:zero-runtime-deps","test:examples:run":"tsc -p tsconfig.examples.json --noEmit && tsx scripts/run-examples.ts","bench:native:check":"pnpm build && tsx scripts/check-benchmark-budgets.ts","release:verify-tag":"tsx scripts/verify-release-tag.ts","smoke:package-manager":"tsx scripts/smoke-package-manager.ts","check:package-contents":"tsx scripts/check-package-contents.ts","test:examples:validate":"tsx scripts/validate-examples.ts","check:zero-runtime-deps":"tsx scripts/check-zero-runtime-deps.ts","release:verify-unpublished":"tsx scripts/verify-npm-version-unpublished.ts"},"_npmUser":{"name":"diegogbrisa","email":"d.garciabrisa@gmail.com"},"_npmVersion":"11.9.0","description":"TypeScript-first pattern matching with matchBy ergonomics, exhaustive checks, and zero runtime dependencies.","directories":{},"sideEffects":false,"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.0.0","devDependencies":{"tsx":"latest","eslint":"^10.2.1","vitest":"latest","prettier":"^3.8.3","ts-pattern":"^5.9.0","typescript":"latest","@types/node":"latest","typescript-eslint":"^8.59.1","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/ts-match_1.0.0_1777465063630_0.018687660335098943","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@diegogbrisa/ts-match","version":"1.0.2","keywords":["typescript","pattern-matching","exhaustive","match","discriminated-unions"],"license":"MIT","_id":"@diegogbrisa/ts-match@1.0.2","maintainers":[{"name":"diegogbrisa","email":"d.garciabrisa@gmail.com"}],"homepage":"https://github.com/DiegoGBrisa/ts-match#readme","bugs":{"url":"https://github.com/DiegoGBrisa/ts-match/issues"},"dist":{"shasum":"5e3efeb29b15d4e1557ef367e9b16f969d5c3b9c","tarball":"https://registry.npmjs.org/@diegogbrisa/ts-match/-/ts-match-1.0.2.tgz","fileCount":49,"integrity":"sha512-McQ6jdhVDW9oPM7aU2QqPxSrt5CED5j3MLikvqiw8FEJQD+4Cixzq8/WgmGK/jMHocJtM5GkVIYwJaH9EtUHBw==","signatures":[{"sig":"MEUCIEm+33+Rsl3DlOy8oovHtY9j1eJ/56rt6qz7ITPM0gC1AiEA59tvxA57LOHo8We4CrvmYw7RJzVGhGXXFisiZSt+w9o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@diegogbrisa%2fts-match@1.0.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":327196},"type":"module","_from":"file:.pack/diegogbrisa-ts-match-1.0.2.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./group":{"types":"./dist/group.d.ts","import":"./dist/group.js"},"./match":{"types":"./dist/match.d.ts","import":"./dist/match.js"},"./errors":{"types":"./dist/errors.d.ts","import":"./dist/errors.js"},"./match-by":{"types":"./dist/match-by.d.ts","import":"./dist/match-by.js"},"./patterns":{"types":"./dist/patterns.d.ts","import":"./dist/patterns.js"},"./assertions":{"types":"./dist/assertions.d.ts","import":"./dist/assertions.js"}},"scripts":{"lint":"eslint \"**/*.ts\"","test":"vitest run","build":"pnpm clean && tsc -p tsconfig.build.json","check":"pnpm lint && pnpm format:check && pnpm build && pnpm typecheck:only && pnpm test:type && pnpm test:diagnostics && pnpm test:coverage && pnpm smoke:exports && pnpm test:docs && pnpm test:examples:validate && pnpm test:examples:run","clean":"rm -rf dist","format":"prettier . --write","lint:fix":"eslint \"**/*.ts\" --fix","test:docs":"tsx scripts/validate-docs.ts","test:type":"tsc -p tsconfig.type-tests.json --noEmit","typecheck":"pnpm build && pnpm typecheck:only","pack:check":"pnpm build && pnpm pack:check:only","bench:types":"tsc -p tsconfig.type-bench.json --noEmit --extendedDiagnostics","bench:native":"pnpm build && tsx benchmarks/native.ts","format:check":"prettier . --check","bench:compare":"pnpm build && tsx benchmarks/compare-ts-pattern.ts","check:commits":"tsx scripts/check-conventional-commits.ts","release:notes":"tsx scripts/extract-release-notes.ts","smoke:exports":"tsx scripts/smoke-exports.ts","test:coverage":"vitest run --coverage","test:examples":"pnpm build && pnpm test:examples:validate && pnpm test:examples:run","bench:dispatch":"tsx benchmarks/dispatch.ts","typecheck:only":"tsc -p tsconfig.json --noEmit","pack:check:only":"rm -rf .pack && mkdir -p .pack && pnpm pack --pack-destination .pack --json && pnpm check:package-contents && tsx scripts/smoke-tarball.ts","typecheck:types":"pnpm test:type","test:diagnostics":"tsx scripts/check-diagnostics.ts","release:preflight":"pnpm check && pnpm bench:types && pnpm bench:native:check:only && pnpm pack:check:only && pnpm audit --prod && pnpm check:zero-runtime-deps","test:examples:run":"tsc -p tsconfig.examples.json --noEmit && tsx scripts/run-examples.ts","bench:native:check":"pnpm build && pnpm bench:native:check:only","release:verify-tag":"tsx scripts/verify-release-tag.ts","smoke:package-manager":"tsx scripts/smoke-package-manager.ts","check:package-contents":"tsx scripts/check-package-contents.ts","test:examples:validate":"tsx scripts/validate-examples.ts","bench:native:check:only":"tsx scripts/check-benchmark-budgets.ts","check:zero-runtime-deps":"tsx scripts/check-zero-runtime-deps.ts","release:verify-unpublished":"tsx scripts/verify-npm-version-unpublished.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:dba2a1ac-602d-4b63-9c89-cacbc92d06a6"}},"_resolved":"/home/runner/work/ts-match/ts-match/.pack/diegogbrisa-ts-match-1.0.2.tgz","_integrity":"sha512-McQ6jdhVDW9oPM7aU2QqPxSrt5CED5j3MLikvqiw8FEJQD+4Cixzq8/WgmGK/jMHocJtM5GkVIYwJaH9EtUHBw==","repository":{"url":"git+https://github.com/DiegoGBrisa/ts-match.git","type":"git"},"_npmVersion":"11.11.0","description":"TypeScript-first pattern matching with matchBy ergonomics, exhaustive checks, and zero runtime dependencies.","directories":{},"sideEffects":false,"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"latest","eslint":"^10.2.1","vitest":"latest","prettier":"^3.8.3","ts-pattern":"^5.9.0","typescript":"latest","@types/node":"latest","typescript-eslint":"^8.59.1","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/ts-match_1.0.2_1777538107398_0.47283376882255124","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@diegogbrisa/ts-match","version":"1.0.3","keywords":["typescript","pattern-matching","exhaustive","match","discriminated-unions"],"license":"MIT","_id":"@diegogbrisa/ts-match@1.0.3","maintainers":[{"name":"diegogbrisa","email":"d.garciabrisa@gmail.com"}],"homepage":"https://github.com/DiegoGBrisa/ts-match#readme","bugs":{"url":"https://github.com/DiegoGBrisa/ts-match/issues"},"dist":{"shasum":"edcb97c3026de2e91a45feffe93f86b5971bf58d","tarball":"https://registry.npmjs.org/@diegogbrisa/ts-match/-/ts-match-1.0.3.tgz","fileCount":49,"integrity":"sha512-9K5kt4stKh939/5wNIQfGEflOoRZD0Ydmz/6wGHQaxUJ+fqtL2RCFCTYTOypHPCtZb3enjO1K8J75saiC4EosA==","signatures":[{"sig":"MEUCIQCVd9iwVSvLzKZ4pG+WyS8gLOWGJUDH716TJVBhEkD3yQIgfjgZXVILkKMkOM/hI0JCPRjyIoxJ05eOXsT0/Mo7KEU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@diegogbrisa%2fts-match@1.0.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":328629},"type":"module","_from":"file:.pack/diegogbrisa-ts-match-1.0.3.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./group":{"types":"./dist/group.d.ts","import":"./dist/group.js"},"./match":{"types":"./dist/match.d.ts","import":"./dist/match.js"},"./errors":{"types":"./dist/errors.d.ts","import":"./dist/errors.js"},"./match-by":{"types":"./dist/match-by.d.ts","import":"./dist/match-by.js"},"./patterns":{"types":"./dist/patterns.d.ts","import":"./dist/patterns.js"},"./assertions":{"types":"./dist/assertions.d.ts","import":"./dist/assertions.js"}},"scripts":{"lint":"eslint \"**/*.ts\"","test":"vitest run","build":"pnpm clean && tsc -p tsconfig.build.json","check":"pnpm lint && pnpm format:check && pnpm build && pnpm typecheck:only && pnpm test:type && pnpm test:diagnostics && pnpm test:coverage && pnpm smoke:exports && pnpm test:docs && pnpm test:examples:validate && pnpm test:examples:run","clean":"rm -rf dist","format":"prettier . --write","lint:fix":"eslint \"**/*.ts\" --fix","test:docs":"tsx scripts/validate-docs.ts","test:type":"tsc -p tsconfig.type-tests.json --noEmit","typecheck":"pnpm build && pnpm typecheck:only","pack:check":"pnpm build && pnpm pack:check:only","bench:types":"tsc -p tsconfig.type-bench.json --noEmit --extendedDiagnostics","bench:native":"pnpm build && tsx benchmarks/native.ts","format:check":"prettier . --check","bench:compare":"pnpm build && tsx benchmarks/compare-ts-pattern.ts","check:commits":"tsx scripts/check-conventional-commits.ts","release:notes":"tsx scripts/extract-release-notes.ts","smoke:exports":"tsx scripts/smoke-exports.ts","test:coverage":"vitest run --coverage","test:examples":"pnpm build && pnpm test:examples:validate && pnpm test:examples:run","bench:dispatch":"tsx benchmarks/dispatch.ts","typecheck:only":"tsc -p tsconfig.json --noEmit","pack:check:only":"rm -rf .pack && mkdir -p .pack && pnpm pack --pack-destination .pack --json && pnpm check:package-contents && tsx scripts/smoke-tarball.ts","typecheck:types":"pnpm test:type","test:diagnostics":"tsx scripts/check-diagnostics.ts","release:preflight":"pnpm check && pnpm bench:types && pnpm bench:native:check:only && pnpm pack:check:only && pnpm audit --prod && pnpm check:zero-runtime-deps","test:examples:run":"tsc -p tsconfig.examples.json --noEmit && tsx scripts/run-examples.ts","bench:native:check":"pnpm build && pnpm bench:native:check:only","release:verify-tag":"tsx scripts/verify-release-tag.ts","smoke:package-manager":"tsx scripts/smoke-package-manager.ts","check:package-contents":"tsx scripts/check-package-contents.ts","test:examples:validate":"tsx scripts/validate-examples.ts","bench:native:check:only":"tsx scripts/check-benchmark-budgets.ts","check:zero-runtime-deps":"tsx scripts/check-zero-runtime-deps.ts","release:verify-unpublished":"tsx scripts/verify-npm-version-unpublished.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:dba2a1ac-602d-4b63-9c89-cacbc92d06a6"}},"_resolved":"/home/runner/work/ts-match/ts-match/.pack/diegogbrisa-ts-match-1.0.3.tgz","_integrity":"sha512-9K5kt4stKh939/5wNIQfGEflOoRZD0Ydmz/6wGHQaxUJ+fqtL2RCFCTYTOypHPCtZb3enjO1K8J75saiC4EosA==","repository":{"url":"git+https://github.com/DiegoGBrisa/ts-match.git","type":"git"},"_npmVersion":"11.11.0","description":"TypeScript-first pattern matching with matchBy ergonomics, exhaustive checks, and zero runtime dependencies.","directories":{},"sideEffects":false,"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"latest","eslint":"^10.2.1","vitest":"latest","prettier":"^3.8.3","ts-pattern":"^5.9.0","typescript":"latest","@types/node":"latest","typescript-eslint":"^8.59.1","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/ts-match_1.0.3_1777538686646_0.9419960791065523","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@diegogbrisa/ts-match","version":"1.1.0","keywords":["typescript","pattern-matching","exhaustive","match","discriminated-unions"],"license":"MIT","_id":"@diegogbrisa/ts-match@1.1.0","maintainers":[{"name":"diegogbrisa","email":"d.garciabrisa@gmail.com"}],"homepage":"https://github.com/DiegoGBrisa/ts-match#readme","bugs":{"url":"https://github.com/DiegoGBrisa/ts-match/issues"},"dist":{"shasum":"011cb3b076dad0f1fd4a306533ad7c9a2a9fecc0","tarball":"https://registry.npmjs.org/@diegogbrisa/ts-match/-/ts-match-1.1.0.tgz","fileCount":49,"integrity":"sha512-fz/1DTKcEJsrw+ip+Dy8n7LIDSH6Ob2gL9/8ghjh8GGaGZnGk458avD+T+SKoWhgtSPJz5NiIboGx75B+zex/w==","signatures":[{"sig":"MEQCICTAH0tXJXqObfMhYloakKcuEQXv+zk3rVVmJ9NNQXVBAiAlIrcQR+8pmPqUAdGaPuC5X/+MJLeOgsQcDb2u4L+Q4A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@diegogbrisa%2fts-match@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":350689},"type":"module","_from":"file:.pack/diegogbrisa-ts-match-1.1.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./group":{"types":"./dist/group.d.ts","import":"./dist/group.js"},"./match":{"types":"./dist/match.d.ts","import":"./dist/match.js"},"./errors":{"types":"./dist/errors.d.ts","import":"./dist/errors.js"},"./match-by":{"types":"./dist/match-by.d.ts","import":"./dist/match-by.js"},"./patterns":{"types":"./dist/patterns.d.ts","import":"./dist/patterns.js"},"./assertions":{"types":"./dist/assertions.d.ts","import":"./dist/assertions.js"}},"scripts":{"lint":"eslint \"**/*.ts\"","test":"vitest run","build":"pnpm clean && tsc -p tsconfig.build.json","check":"pnpm lint && pnpm format:check && pnpm build && pnpm typecheck:only && pnpm test:type && pnpm test:diagnostics && pnpm test:editor-dx && pnpm test:coverage && pnpm smoke:exports && pnpm test:docs && pnpm test:examples:validate && pnpm test:examples:run","clean":"rm -rf dist","format":"prettier . --write","lint:fix":"eslint \"**/*.ts\" --fix","test:docs":"tsx scripts/validate-docs.ts","test:type":"tsc -p tsconfig.type-tests.json --noEmit","typecheck":"pnpm build && pnpm typecheck:only","pack:check":"pnpm build && pnpm pack:check:only","bench:types":"tsc -p tsconfig.type-bench.json --noEmit --extendedDiagnostics","bench:native":"pnpm build && tsx benchmarks/native.ts","format:check":"prettier . --check","bench:compare":"pnpm build && tsx benchmarks/compare-ts-pattern.ts","check:commits":"tsx scripts/check-conventional-commits.ts","release:notes":"tsx scripts/extract-release-notes.ts","smoke:exports":"tsx scripts/smoke-exports.ts","test:coverage":"vitest run --coverage --exclude tests/editor-dx.test.ts","test:examples":"pnpm build && pnpm test:examples:validate && pnpm test:examples:run","bench:dispatch":"tsx benchmarks/dispatch.ts","test:editor-dx":"vitest run tests/editor-dx.test.ts","typecheck:only":"tsc -p tsconfig.json --noEmit","pack:check:only":"rm -rf .pack && mkdir -p .pack && pnpm pack --pack-destination .pack --json && pnpm check:package-contents && tsx scripts/smoke-tarball.ts","typecheck:types":"pnpm test:type","test:diagnostics":"tsx scripts/check-diagnostics.ts","release:preflight":"pnpm check && pnpm bench:types && pnpm bench:native:check:only && pnpm pack:check:only && pnpm audit --prod && pnpm check:zero-runtime-deps","test:examples:run":"tsc -p tsconfig.examples.json --noEmit && tsx scripts/run-examples.ts","bench:native:check":"pnpm build && pnpm bench:native:check:only","release:verify-tag":"tsx scripts/verify-release-tag.ts","smoke:package-manager":"tsx scripts/smoke-package-manager.ts","check:package-contents":"tsx scripts/check-package-contents.ts","test:examples:validate":"tsx scripts/validate-examples.ts","bench:native:check:only":"tsx scripts/check-benchmark-budgets.ts","check:zero-runtime-deps":"tsx scripts/check-zero-runtime-deps.ts","release:verify-unpublished":"tsx scripts/verify-npm-version-unpublished.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:dba2a1ac-602d-4b63-9c89-cacbc92d06a6"}},"_resolved":"/home/runner/work/ts-match/ts-match/.pack/diegogbrisa-ts-match-1.1.0.tgz","_integrity":"sha512-fz/1DTKcEJsrw+ip+Dy8n7LIDSH6Ob2gL9/8ghjh8GGaGZnGk458avD+T+SKoWhgtSPJz5NiIboGx75B+zex/w==","repository":{"url":"git+https://github.com/DiegoGBrisa/ts-match.git","type":"git"},"_npmVersion":"11.11.0","description":"TypeScript-first pattern matching with matchBy ergonomics, exhaustive checks, and zero runtime dependencies.","directories":{},"sideEffects":false,"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"latest","eslint":"^10.2.1","vitest":"latest","prettier":"^3.8.3","ts-pattern":"^5.9.0","typescript":"latest","@types/node":"latest","typescript-eslint":"^8.59.1","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/ts-match_1.1.0_1777574153210_0.7046951931764796","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@diegogbrisa/ts-match","version":"1.2.0","keywords":["typescript","pattern-matching","exhaustive","match","discriminated-unions"],"license":"MIT","_id":"@diegogbrisa/ts-match@1.2.0","maintainers":[{"name":"diegogbrisa","email":"d.garciabrisa@gmail.com"}],"homepage":"https://github.com/DiegoGBrisa/ts-match#readme","bugs":{"url":"https://github.com/DiegoGBrisa/ts-match/issues"},"dist":{"shasum":"257f22c136adc54c4f4e92539fa47cd45cc926c1","tarball":"https://registry.npmjs.org/@diegogbrisa/ts-match/-/ts-match-1.2.0.tgz","fileCount":51,"integrity":"sha512-yW1WOHocOmXUZYYcgegwcswyCgfrlYczSIuedWx30z2FYzDV0KBvTyDV0kvXzkh9H+1aCEmxNoUsM9DwGBTIsA==","signatures":[{"sig":"MEUCIQDPdlrns5kdxO329WjFsuh+vGi+6ZyaXY1c2ejPmHdSlgIgJkOnZITZOZRA/ukiUBF5Q32YhZVpkFaAPilNV1RHD0g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@diegogbrisa%2fts-match@1.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":402615},"type":"module","_from":"file:.pack/diegogbrisa-ts-match-1.2.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./group":{"types":"./dist/group.d.ts","import":"./dist/group.js"},"./match":{"types":"./dist/match.d.ts","import":"./dist/match.js"},"./errors":{"types":"./dist/errors.d.ts","import":"./dist/errors.js"},"./match-by":{"types":"./dist/match-by.d.ts","import":"./dist/match-by.js"},"./patterns":{"types":"./dist/patterns.d.ts","import":"./dist/patterns.js"},"./assertions":{"types":"./dist/assertions.d.ts","import":"./dist/assertions.js"}},"scripts":{"lint":"eslint \"**/*.ts\"","test":"vitest run","build":"pnpm clean && tsc -p tsconfig.build.json","check":"pnpm lint && pnpm format:check && pnpm build && pnpm typecheck:only && pnpm test:type && pnpm test:diagnostics && pnpm test:editor-dx && pnpm test:coverage && pnpm smoke:exports && pnpm test:docs && pnpm test:examples:validate && pnpm test:examples:run","clean":"rm -rf dist","format":"prettier . --write","lint:fix":"eslint \"**/*.ts\" --fix","test:docs":"tsx scripts/validate-docs.ts","test:type":"tsc -p tsconfig.type-tests.json --noEmit","typecheck":"pnpm build && pnpm typecheck:only","pack:check":"pnpm build && pnpm pack:check:only","bench:types":"tsc -p tsconfig.type-bench.json --noEmit --extendedDiagnostics","bench:native":"pnpm build && tsx benchmarks/native.ts","format:check":"prettier . --check","bench:compare":"pnpm build && tsx benchmarks/compare-ts-pattern.ts","check:commits":"tsx scripts/check-conventional-commits.ts","release:notes":"tsx scripts/extract-release-notes.ts","smoke:exports":"tsx scripts/smoke-exports.ts","test:coverage":"vitest run --coverage --exclude tests/editor-dx.test.ts","test:examples":"pnpm build && pnpm test:examples:validate && pnpm test:examples:run","bench:dispatch":"tsx benchmarks/dispatch.ts","test:editor-dx":"vitest run tests/editor-dx.test.ts","typecheck:only":"tsc -p tsconfig.json --noEmit","pack:check:only":"rm -rf .pack && mkdir -p .pack && pnpm pack --pack-destination .pack --json && pnpm check:package-contents && tsx scripts/smoke-tarball.ts","typecheck:types":"pnpm test:type","test:diagnostics":"tsx scripts/check-diagnostics.ts","release:preflight":"pnpm check && pnpm bench:types && pnpm bench:native:check:only && pnpm pack:check:only && pnpm audit --prod && pnpm check:zero-runtime-deps","test:examples:run":"tsc -p tsconfig.examples.json --noEmit && tsx scripts/run-examples.ts","bench:native:check":"pnpm build && pnpm bench:native:check:only","release:verify-tag":"tsx scripts/verify-release-tag.ts","smoke:package-manager":"tsx scripts/smoke-package-manager.ts","check:package-contents":"tsx scripts/check-package-contents.ts","test:examples:validate":"tsx scripts/validate-examples.ts","bench:native:check:only":"tsx scripts/check-benchmark-budgets.ts","check:zero-runtime-deps":"tsx scripts/check-zero-runtime-deps.ts","release:verify-unpublished":"tsx scripts/verify-npm-version-unpublished.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:dba2a1ac-602d-4b63-9c89-cacbc92d06a6"}},"_resolved":"/home/runner/work/ts-match/ts-match/.pack/diegogbrisa-ts-match-1.2.0.tgz","_integrity":"sha512-yW1WOHocOmXUZYYcgegwcswyCgfrlYczSIuedWx30z2FYzDV0KBvTyDV0kvXzkh9H+1aCEmxNoUsM9DwGBTIsA==","repository":{"url":"git+https://github.com/DiegoGBrisa/ts-match.git","type":"git"},"_npmVersion":"11.11.0","description":"TypeScript-first pattern matching with matchBy ergonomics, exhaustive checks, and zero runtime dependencies.","directories":{},"sideEffects":false,"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"latest","eslint":"^10.2.1","vitest":"latest","prettier":"^3.8.3","ts-pattern":"^5.9.0","typescript":"latest","@types/node":"latest","typescript-eslint":"^8.59.1","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/ts-match_1.2.0_1777884365788_0.26505354948403537","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@diegogbrisa/ts-match","version":"1.3.0","keywords":["typescript","pattern-matching","exhaustive","match","discriminated-union","discriminated-unions","assert-never","type-safety","reducer","union"],"license":"MIT","_id":"@diegogbrisa/ts-match@1.3.0","maintainers":[{"name":"diegogbrisa","email":"d.garciabrisa@gmail.com"}],"homepage":"https://github.com/DiegoGBrisa/ts-match#readme","bugs":{"url":"https://github.com/DiegoGBrisa/ts-match/issues"},"dist":{"shasum":"2063f751de341836677f029c3e8390f7f8a163ea","tarball":"https://registry.npmjs.org/@diegogbrisa/ts-match/-/ts-match-1.3.0.tgz","fileCount":52,"integrity":"sha512-zCgFSv1Hc6r8g4SH5GZLMlhhQ2iA438gXgUvgDnIeiyNqNl9G7m95naTTSupR8GdSzOf5bmTDHo9S0eawOozCA==","signatures":[{"sig":"MEYCIQDfc8O88LSpZuzskXyG7tYOsH/r9SagiOLPNFLxQ7aunAIhAITEbj1dabjNcdw1s/cgxtyHqjOuRGhzhQos2qkOOdhR","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@diegogbrisa%2fts-match@1.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":454926},"type":"module","_from":"file:.pack/diegogbrisa-ts-match-1.3.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./group":{"types":"./dist/group.d.ts","import":"./dist/group.js"},"./match":{"types":"./dist/match.d.ts","import":"./dist/match.js"},"./errors":{"types":"./dist/errors.d.ts","import":"./dist/errors.js"},"./match-by":{"types":"./dist/match-by.d.ts","import":"./dist/match-by.js"},"./patterns":{"types":"./dist/patterns.d.ts","import":"./dist/patterns.js"},"./assertions":{"types":"./dist/assertions.d.ts","import":"./dist/assertions.js"}},"scripts":{"lint":"eslint \"**/*.ts\"","test":"vitest run","build":"pnpm clean && tsc -p tsconfig.build.json","check":"pnpm lint && pnpm format:check && pnpm build && pnpm typecheck:only && pnpm test:type && pnpm test:diagnostics && pnpm test:editor-dx && pnpm test:coverage && pnpm smoke:exports && pnpm test:docs && pnpm test:examples:validate && pnpm test:examples:run","clean":"rm -rf dist","format":"prettier . --write","lint:fix":"eslint \"**/*.ts\" --fix","test:docs":"tsx scripts/validate-docs.ts","test:type":"tsc -p tsconfig.type-tests.json --noEmit","typecheck":"pnpm build && pnpm typecheck:only","pack:check":"pnpm build && pnpm pack:check:only","bench:types":"tsc -p tsconfig.type-bench.json --noEmit --extendedDiagnostics","bench:native":"pnpm build && tsx benchmarks/native.ts","format:check":"prettier . --check","bench:compare":"pnpm build && tsx benchmarks/compare-ts-pattern.ts","check:commits":"tsx scripts/check-conventional-commits.ts","release:notes":"tsx scripts/extract-release-notes.ts","smoke:exports":"tsx scripts/smoke-exports.ts","test:coverage":"vitest run --coverage --exclude tests/editor-dx.test.ts","test:examples":"pnpm build && pnpm test:examples:validate && pnpm test:examples:run","bench:dispatch":"tsx benchmarks/dispatch.ts","test:editor-dx":"vitest run tests/editor-dx.test.ts","typecheck:only":"tsc -p tsconfig.json --noEmit","pack:check:only":"rm -rf .pack && mkdir -p .pack && pnpm pack --pack-destination .pack --json && pnpm check:package-contents && tsx scripts/smoke-tarball.ts","typecheck:types":"pnpm test:type","test:diagnostics":"tsx scripts/check-diagnostics.ts","release:preflight":"pnpm check && pnpm bench:types && pnpm bench:native:check:only && pnpm pack:check:only && pnpm audit --prod && pnpm check:zero-runtime-deps","test:examples:run":"tsc -p tsconfig.examples.json --noEmit && tsx scripts/run-examples.ts","bench:native:check":"pnpm build && pnpm bench:native:check:only","release:verify-tag":"tsx scripts/verify-release-tag.ts","test:temporal-real":"vitest run tests/temporal-real.test.mjs","smoke:package-manager":"tsx scripts/smoke-package-manager.ts","test:temporal-browser":"pnpm build && node scripts/check-browser-temporal.mjs","check:package-contents":"tsx scripts/check-package-contents.ts","test:examples:validate":"tsx scripts/validate-examples.ts","bench:native:check:only":"tsx scripts/check-benchmark-budgets.ts","check:zero-runtime-deps":"tsx scripts/check-zero-runtime-deps.ts","release:verify-unpublished":"tsx scripts/verify-npm-version-unpublished.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:dba2a1ac-602d-4b63-9c89-cacbc92d06a6"}},"_resolved":"/home/runner/work/ts-match/ts-match/.pack/diegogbrisa-ts-match-1.3.0.tgz","_integrity":"sha512-zCgFSv1Hc6r8g4SH5GZLMlhhQ2iA438gXgUvgDnIeiyNqNl9G7m95naTTSupR8GdSzOf5bmTDHo9S0eawOozCA==","repository":{"url":"git+https://github.com/DiegoGBrisa/ts-match.git","type":"git"},"_npmVersion":"11.13.0","description":"TypeScript-first pattern matching with matchBy ergonomics, exhaustive checks, and zero runtime dependencies.","directories":{},"sideEffects":false,"_nodeVersion":"24.16.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"latest","eslint":"^10.2.1","vitest":"latest","prettier":"^3.8.3","playwright":"^1.60.0","ts-pattern":"^5.9.0","typescript":"latest","@types/node":"latest","typescript-eslint":"^8.59.1","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/ts-match_1.3.0_1780572746200_0.9707261776978704","host":"s3://npm-registry-packages-npm-production"}},"1.4.0":{"name":"@diegogbrisa/ts-match","version":"1.4.0","keywords":["typescript","pattern-matching","exhaustive","match","discriminated-union","discriminated-unions","assert-never","type-safety","reducer","union"],"license":"MIT","_id":"@diegogbrisa/ts-match@1.4.0","maintainers":[{"name":"diegogbrisa","email":"d.garciabrisa@gmail.com"}],"homepage":"https://github.com/DiegoGBrisa/ts-match#readme","bugs":{"url":"https://github.com/DiegoGBrisa/ts-match/issues"},"dist":{"shasum":"b76b63204b97d221b31779d934d3cb9c20d37e83","tarball":"https://registry.npmjs.org/@diegogbrisa/ts-match/-/ts-match-1.4.0.tgz","fileCount":53,"integrity":"sha512-bzwjiYnZjs8jJ9NYp8zEb/ytOdvhnZTCmAMK4h0a70mVYvaqzqMm/bIYgB9yHEw/XzYkRAK6HcRhCrcd5BbZfw==","signatures":[{"sig":"MEUCIDkM947y5In5/QevuvObbTJ7wKhaAzMeYIn/LS20YQS0AiEA2uJ2LoZMNvWnSA2uDtxo8iILF5KwuyZeYNnSftayT6Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@diegogbrisa%2fts-match@1.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":494075},"type":"module","_from":"file:.pack/diegogbrisa-ts-match-1.4.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./group":{"types":"./dist/group.d.ts","import":"./dist/group.js"},"./match":{"types":"./dist/match.d.ts","import":"./dist/match.js"},"./errors":{"types":"./dist/errors.d.ts","import":"./dist/errors.js"},"./match-by":{"types":"./dist/match-by.d.ts","import":"./dist/match-by.js"},"./patterns":{"types":"./dist/patterns.d.ts","import":"./dist/patterns.js"},"./assertions":{"types":"./dist/assertions.d.ts","import":"./dist/assertions.js"}},"scripts":{"lint":"eslint \"**/*.ts\"","test":"vitest run","build":"pnpm clean && tsc -p tsconfig.build.json","check":"pnpm lint && pnpm format:check && pnpm build && pnpm typecheck:only && pnpm test:type && pnpm test:diagnostics && pnpm test:editor-dx && pnpm test:coverage && pnpm smoke:exports && pnpm test:docs && pnpm test:examples:validate && pnpm test:examples:run","clean":"rm -rf dist","format":"prettier . --write","lint:fix":"eslint \"**/*.ts\" --fix","test:docs":"tsx scripts/validate-docs.ts","test:type":"tsc -p tsconfig.type-tests.json --noEmit","typecheck":"pnpm build && pnpm typecheck:only","pack:check":"pnpm build && pnpm pack:check:only","bench:types":"tsc -p tsconfig.type-bench.json --noEmit --extendedDiagnostics","bench:native":"pnpm build && tsx benchmarks/native.ts","format:check":"prettier . --check","bench:compare":"pnpm build && tsx benchmarks/compare-ts-pattern.ts","check:commits":"tsx scripts/check-conventional-commits.ts","release:notes":"tsx scripts/extract-release-notes.ts","smoke:exports":"tsx scripts/smoke-exports.ts","test:coverage":"vitest run --coverage --exclude tests/editor-dx.test.ts","test:examples":"pnpm build && pnpm test:examples:validate && pnpm test:examples:run","bench:dispatch":"tsx benchmarks/dispatch.ts","test:editor-dx":"vitest run tests/editor-dx.test.ts","typecheck:only":"tsc -p tsconfig.json --noEmit","pack:check:only":"rm -rf .pack && mkdir -p .pack && pnpm pack --pack-destination .pack --json && pnpm check:package-contents && tsx scripts/smoke-tarball.ts","typecheck:types":"pnpm test:type","test:diagnostics":"tsx scripts/check-diagnostics.ts","release:preflight":"pnpm check && pnpm bench:types && pnpm bench:native:check:only && pnpm pack:check:only && pnpm audit --prod && pnpm check:zero-runtime-deps","test:examples:run":"tsc -p tsconfig.examples.json --noEmit && tsx scripts/run-examples.ts","bench:native:check":"pnpm build && pnpm bench:native:check:only","release:verify-tag":"tsx scripts/verify-release-tag.ts","test:temporal-real":"vitest run tests/temporal-real.test.mjs","smoke:package-manager":"tsx scripts/smoke-package-manager.ts","test:temporal-browser":"pnpm build && node scripts/check-browser-temporal.mjs","check:package-contents":"tsx scripts/check-package-contents.ts","test:examples:validate":"tsx scripts/validate-examples.ts","bench:native:check:only":"tsx scripts/check-benchmark-budgets.ts","check:zero-runtime-deps":"tsx scripts/check-zero-runtime-deps.ts","release:verify-unpublished":"tsx scripts/verify-npm-version-unpublished.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:dba2a1ac-602d-4b63-9c89-cacbc92d06a6"}},"_resolved":"/home/runner/work/ts-match/ts-match/.pack/diegogbrisa-ts-match-1.4.0.tgz","_integrity":"sha512-bzwjiYnZjs8jJ9NYp8zEb/ytOdvhnZTCmAMK4h0a70mVYvaqzqMm/bIYgB9yHEw/XzYkRAK6HcRhCrcd5BbZfw==","repository":{"url":"git+https://github.com/DiegoGBrisa/ts-match.git","type":"git"},"_npmVersion":"11.13.0","description":"TypeScript-first pattern matching with matchBy ergonomics, exhaustive checks, and zero runtime dependencies.","directories":{},"sideEffects":false,"_nodeVersion":"24.16.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"latest","eslint":"^10.2.1","vitest":"latest","prettier":"^3.8.3","playwright":"^1.60.0","ts-pattern":"^5.9.0","typescript":"latest","@types/node":"latest","typescript-eslint":"^8.59.1","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/ts-match_1.4.0_1780644904763_0.6660978553524661","host":"s3://npm-registry-packages-npm-production"}},"1.5.0":{"name":"@diegogbrisa/ts-match","version":"1.5.0","keywords":["typescript","pattern-matching","exhaustive","match","discriminated-union","discriminated-unions","assert-never","type-safety","reducer","union"],"license":"MIT","_id":"@diegogbrisa/ts-match@1.5.0","maintainers":[{"name":"diegogbrisa","email":"d.garciabrisa@gmail.com"}],"homepage":"https://github.com/DiegoGBrisa/ts-match#readme","bugs":{"url":"https://github.com/DiegoGBrisa/ts-match/issues"},"dist":{"shasum":"eb87bba4b0f9f75e48b39f10bb2aa206d1cc2e3a","tarball":"https://registry.npmjs.org/@diegogbrisa/ts-match/-/ts-match-1.5.0.tgz","fileCount":53,"integrity":"sha512-vziQxw+bnSqIawvWHA4RKDeQMxClYcczYQ9ughJKv8SXasWa3wR/HfcacIAxA3LiflM3MzMSKvqWEzwpVzJtig==","signatures":[{"sig":"MEYCIQCAMIJXiDb36kmBl4rPXQeUnAQiv8AtYHpTGnbrQVPYqAIhANBmy97o6jM1BSJjGmucyi/9ulvXf9Bo0/tUUdCjES/v","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@diegogbrisa%2fts-match@1.5.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":543512},"type":"module","_from":"file:.pack/diegogbrisa-ts-match-1.5.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./group":{"types":"./dist/group.d.ts","import":"./dist/group.js"},"./match":{"types":"./dist/match.d.ts","import":"./dist/match.js"},"./errors":{"types":"./dist/errors.d.ts","import":"./dist/errors.js"},"./match-by":{"types":"./dist/match-by.d.ts","import":"./dist/match-by.js"},"./patterns":{"types":"./dist/patterns.d.ts","import":"./dist/patterns.js"},"./assertions":{"types":"./dist/assertions.d.ts","import":"./dist/assertions.js"}},"scripts":{"lint":"eslint \"**/*.ts\"","test":"vitest run","build":"pnpm clean && tsc -p tsconfig.build.json","check":"pnpm lint && pnpm format:check && pnpm build && pnpm typecheck:only && pnpm test:type && pnpm test:diagnostics && pnpm test:editor-dx && pnpm test:coverage && pnpm smoke:exports && pnpm test:docs && pnpm test:examples:validate && pnpm test:examples:run","clean":"rm -rf dist","format":"prettier . --write","lint:fix":"eslint \"**/*.ts\" --fix","test:docs":"tsx scripts/validate-docs.ts","test:type":"tsc -p tsconfig.type-tests.json --noEmit","typecheck":"pnpm build && pnpm typecheck:only","pack:check":"pnpm build && pnpm pack:check:only","bench:types":"tsc -p tsconfig.type-bench.json --noEmit --extendedDiagnostics","bench:native":"pnpm build && tsx benchmarks/native.ts","format:check":"prettier . --check","bench:compare":"pnpm build && tsx benchmarks/compare-ts-pattern.ts","check:commits":"tsx scripts/check-conventional-commits.ts","release:notes":"tsx scripts/extract-release-notes.ts","smoke:exports":"tsx scripts/smoke-exports.ts","test:coverage":"vitest run --coverage --exclude tests/editor-dx.test.ts","test:examples":"pnpm build && pnpm test:examples:validate && pnpm test:examples:run","bench:dispatch":"tsx benchmarks/dispatch.ts","test:editor-dx":"vitest run tests/editor-dx.test.ts","typecheck:only":"tsc -p tsconfig.json --noEmit","pack:check:only":"rm -rf .pack && mkdir -p .pack && pnpm pack --pack-destination .pack --json && pnpm check:package-contents && tsx scripts/smoke-tarball.ts","typecheck:types":"pnpm test:type","test:diagnostics":"tsx scripts/check-diagnostics.ts","release:preflight":"pnpm check && pnpm bench:types && pnpm bench:native:check:only && pnpm pack:check:only && pnpm audit --prod && pnpm check:zero-runtime-deps","test:examples:run":"tsc -p tsconfig.examples.json --noEmit && tsx scripts/run-examples.ts","bench:native:check":"pnpm build && pnpm bench:native:check:only","release:verify-tag":"tsx scripts/verify-release-tag.ts","test:temporal-real":"vitest run tests/temporal-real.test.mjs","smoke:package-manager":"tsx scripts/smoke-package-manager.ts","test:temporal-browser":"pnpm build && node scripts/check-browser-temporal.mjs","check:package-contents":"tsx scripts/check-package-contents.ts","test:examples:validate":"tsx scripts/validate-examples.ts","bench:native:check:only":"tsx scripts/check-benchmark-budgets.ts","check:zero-runtime-deps":"tsx scripts/check-zero-runtime-deps.ts","release:verify-unpublished":"tsx scripts/verify-npm-version-unpublished.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:dba2a1ac-602d-4b63-9c89-cacbc92d06a6"}},"_resolved":"/home/runner/work/ts-match/ts-match/.pack/diegogbrisa-ts-match-1.5.0.tgz","_integrity":"sha512-vziQxw+bnSqIawvWHA4RKDeQMxClYcczYQ9ughJKv8SXasWa3wR/HfcacIAxA3LiflM3MzMSKvqWEzwpVzJtig==","repository":{"url":"git+https://github.com/DiegoGBrisa/ts-match.git","type":"git"},"_npmVersion":"11.13.0","description":"TypeScript-first pattern matching with matchBy ergonomics, exhaustive checks, and zero runtime dependencies.","directories":{},"sideEffects":false,"_nodeVersion":"24.16.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"latest","eslint":"^10.2.1","vitest":"latest","prettier":"^3.8.3","playwright":"^1.60.0","ts-pattern":"^5.9.0","typescript":"latest","@types/node":"latest","typescript-eslint":"^8.59.1","@vitest/coverage-v8":"^4.1.5"},"_npmOperationalInternal":{"tmp":"tmp/ts-match_1.5.0_1780991114334_0.20570229456584532","host":"s3://npm-registry-packages-npm-production"}},"1.6.0":{"name":"@diegogbrisa/ts-match","version":"1.6.0","keywords":["typescript","pattern-matching","exhaustive","match","discriminated-union","discriminated-unions","assert-never","type-safety","reducer","union"],"license":"MIT","_id":"@diegogbrisa/ts-match@1.6.0","maintainers":[{"name":"diegogbrisa","email":"d.garciabrisa@gmail.com"}],"homepage":"https://github.com/DiegoGBrisa/ts-match#readme","bugs":{"url":"https://github.com/DiegoGBrisa/ts-match/issues"},"dist":{"shasum":"f78aad7179282096846c33f11f7cbd815c1898f3","tarball":"https://registry.npmjs.org/@diegogbrisa/ts-match/-/ts-match-1.6.0.tgz","fileCount":141,"integrity":"sha512-fCt20Dl3RVD+UlMR7leznr+FgMFLK9Fbqj3DAC//0KMIpTn625NpVrUfjt1RP7bWZOIkuP2wFCUNip4RJLCDRg==","signatures":[{"sig":"MEYCIQCVvt/1ty6hftAeOqlOWEChNqU7RV2vixHIqsd4ydFTzQIhANrqwuYseTR+uskf6/d9fnIJYtBOXM/mzUdwSyu4DxGS","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@diegogbrisa%2fts-match@1.6.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":571342},"type":"module","_from":"file:.pack/diegogbrisa-ts-match-1.6.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./group":{"types":"./dist/group/index.d.ts","import":"./dist/group/index.js"},"./match":{"types":"./dist/match/index.d.ts","import":"./dist/match/index.js"},"./errors":{"types":"./dist/errors/index.d.ts","import":"./dist/errors/index.js"},"./match-by":{"types":"./dist/match-by/index.d.ts","import":"./dist/match-by/index.js"},"./patterns":{"types":"./dist/patterns/index.d.ts","import":"./dist/patterns/index.js"},"./assertions":{"types":"./dist/assertions/index.d.ts","import":"./dist/assertions/index.js"}},"scripts":{"lint":"pnpm build && pnpm lint:only","test":"vitest run","build":"pnpm clean && tsc -p tsconfig.build.json","check":"pnpm check:architecture && pnpm format:check && pnpm build && pnpm lint:only && pnpm typecheck:only && pnpm typecheck:benchmarks && pnpm test:type && pnpm test:diagnostics && pnpm test:editor-dx && pnpm test:coverage && pnpm smoke:exports && pnpm test:docs && pnpm test:examples:validate && pnpm test:examples:run","clean":"rm -rf dist","format":"prettier . --write","lint:fix":"pnpm build && eslint \"**/*.ts\" --fix","lint:only":"eslint \"**/*.ts\"","test:docs":"tsx scripts/validate-docs.ts","test:type":"tsc -p tsconfig.type-tests.json --noEmit","typecheck":"pnpm build && pnpm typecheck:only && pnpm typecheck:benchmarks","pack:check":"pnpm build && pnpm pack:check:only","bench:types":"tsc -p tsconfig.type-bench.json --noEmit --extendedDiagnostics","bench:native":"pnpm build && tsx benchmarks/native.ts","format:check":"prettier . --check","bench:compare":"pnpm build && tsx benchmarks/compare-ts-pattern.ts","check:commits":"tsx scripts/check-conventional-commits.ts","release:notes":"tsx scripts/extract-release-notes.ts","smoke:exports":"tsx scripts/smoke-exports.ts","test:coverage":"vitest run --config vitest.coverage.config.ts --coverage","test:examples":"pnpm build && pnpm test:examples:validate && pnpm test:examples:run","bench:dispatch":"tsx benchmarks/dispatch.ts","test:editor-dx":"vitest run src/**/__tests__/*editor-dx.test.ts","typecheck:only":"tsc -p tsconfig.json --noEmit","pack:check:only":"rm -rf .pack && mkdir -p .pack && pnpm pack --pack-destination .pack --json && pnpm check:package-contents && tsx scripts/smoke-tarball.ts","typecheck:types":"pnpm test:type","test:diagnostics":"tsx scripts/check-diagnostics.ts","release:preflight":"pnpm check && pnpm bench:types && pnpm bench:native:check:only && pnpm pack:check:only && pnpm audit --prod && pnpm check:zero-runtime-deps","test:examples:run":"tsc -p tsconfig.examples.json --noEmit && tsx scripts/run-examples.ts","bench:native:check":"pnpm build && pnpm bench:native:check:only","check:architecture":"tsx scripts/check-architecture.ts","release:verify-tag":"tsx scripts/verify-release-tag.ts","test:temporal-real":"vitest run tests/integration/temporal-real.test.mjs","typecheck:benchmarks":"tsc -p tsconfig.benchmarks.package.json --noEmit && tsc -p tsconfig.benchmarks.dispatch.json --noEmit","smoke:package-manager":"tsx scripts/smoke-package-manager.ts","test:temporal-browser":"pnpm build && node scripts/check-browser-temporal.mjs","check:package-contents":"tsx scripts/check-package-contents.ts","test:examples:validate":"tsx scripts/validate-examples.ts","bench:native:check:only":"tsx scripts/check-benchmark-budgets.ts","check:zero-runtime-deps":"tsx scripts/check-zero-runtime-deps.ts","release:verify-unpublished":"tsx scripts/verify-npm-version-unpublished.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:dba2a1ac-602d-4b63-9c89-cacbc92d06a6"}},"_resolved":"/home/runner/work/ts-match/ts-match/.pack/diegogbrisa-ts-match-1.6.0.tgz","_integrity":"sha512-fCt20Dl3RVD+UlMR7leznr+FgMFLK9Fbqj3DAC//0KMIpTn625NpVrUfjt1RP7bWZOIkuP2wFCUNip4RJLCDRg==","repository":{"url":"git+https://github.com/DiegoGBrisa/ts-match.git","type":"git"},"_npmVersion":"11.13.0","description":"TypeScript-first pattern matching with matchBy ergonomics, exhaustive checks, and zero runtime dependencies.","directories":{},"sideEffects":false,"_nodeVersion":"24.16.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"latest","eslint":"^10.2.1","vitest":"latest","prettier":"^3.8.3","playwright":"^1.60.0","ts-pattern":"^5.9.0","typescript":"latest","@types/node":"latest","typescript-eslint":"^8.59.1","@vitest/coverage-v8":"^4.1.5","eslint-plugin-import-x":"^4.16.2","eslint-import-resolver-typescript":"^4.4.5"},"_npmOperationalInternal":{"tmp":"tmp/ts-match_1.6.0_1781170026645_0.4662228845697294","host":"s3://npm-registry-packages-npm-production"}},"1.6.1":{"name":"@diegogbrisa/ts-match","version":"1.6.1","keywords":["typescript","pattern-matching","exhaustive","match","discriminated-union","discriminated-unions","assert-never","type-safety","reducer","union"],"license":"MIT","_id":"@diegogbrisa/ts-match@1.6.1","maintainers":[{"name":"diegogbrisa","email":"d.garciabrisa@gmail.com"}],"homepage":"https://github.com/DiegoGBrisa/ts-match#readme","bugs":{"url":"https://github.com/DiegoGBrisa/ts-match/issues"},"dist":{"shasum":"165b1f77395b15878c1003000a90c7d5871ab64d","tarball":"https://registry.npmjs.org/@diegogbrisa/ts-match/-/ts-match-1.6.1.tgz","fileCount":195,"integrity":"sha512-CJCALxChEbr8gCmdAPHOQv0kilTfrRfAGwg8MS64iIO/vWPBBvQQ2qyk3pb7xosUelkmdLCRD+zJvWkjGJEq/A==","signatures":[{"sig":"MEUCIQDOlsQSeAkNv2tuoy1VUXDJgT0Mvj+UkhCAinVq/3ZS5AIgdxSaIiSNol5U+VGn8BKtIRUh9fNskR/CL9YwDq9Gpyc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@diegogbrisa%2fts-match@1.6.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":713714},"type":"module","_from":"file:.pack/diegogbrisa-ts-match-1.6.1.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist-cjs/index.js"},"./group":{"types":"./dist/group/index.d.ts","import":"./dist/group/index.js","require":"./dist-cjs/group/index.js"},"./match":{"types":"./dist/match/index.d.ts","import":"./dist/match/index.js","require":"./dist-cjs/match/index.js"},"./errors":{"types":"./dist/errors/index.d.ts","import":"./dist/errors/index.js","require":"./dist-cjs/errors/index.js"},"./match-by":{"types":"./dist/match-by/index.d.ts","import":"./dist/match-by/index.js","require":"./dist-cjs/match-by/index.js"},"./patterns":{"types":"./dist/patterns/index.d.ts","import":"./dist/patterns/index.js","require":"./dist-cjs/patterns/index.js"},"./assertions":{"types":"./dist/assertions/index.d.ts","import":"./dist/assertions/index.js","require":"./dist-cjs/assertions/index.js"}},"scripts":{"lint":"pnpm build && pnpm lint:only","test":"vitest run","build":"pnpm clean && tsc -p tsconfig.build.json && tsc -p tsconfig.cjs.json && tsx scripts/write-cjs-package-json.ts","check":"pnpm check:architecture && pnpm format:check && pnpm build && pnpm lint:only && pnpm typecheck:only && pnpm typecheck:benchmarks && pnpm test:type && pnpm test:diagnostics && pnpm test:editor-dx && pnpm test:coverage && pnpm smoke:exports && pnpm test:docs && pnpm test:examples:validate && pnpm test:examples:run","clean":"rm -rf dist dist-cjs","format":"prettier . --write","lint:fix":"pnpm build && eslint \"**/*.ts\" --fix","lint:only":"eslint \"**/*.ts\"","test:docs":"tsx scripts/validate-docs.ts","test:type":"tsc -p tsconfig.type-tests.json --noEmit","typecheck":"pnpm build && pnpm typecheck:only && pnpm typecheck:benchmarks","pack:check":"pnpm build && pnpm pack:check:only","bench:types":"tsc -p tsconfig.type-bench.json --noEmit --extendedDiagnostics","bench:native":"pnpm build && tsx benchmarks/native.ts","format:check":"prettier . --check","bench:compare":"pnpm build && tsx benchmarks/compare-ts-pattern.ts","check:commits":"tsx scripts/check-conventional-commits.ts","release:notes":"tsx scripts/extract-release-notes.ts","smoke:exports":"tsx scripts/smoke-exports.ts","test:coverage":"vitest run --config vitest.coverage.config.ts --coverage","test:examples":"pnpm build && pnpm test:examples:validate && pnpm test:examples:run","bench:dispatch":"tsx benchmarks/dispatch.ts","test:editor-dx":"vitest run src/**/__tests__/*editor-dx.test.ts","typecheck:only":"tsc -p tsconfig.json --noEmit","pack:check:only":"rm -rf .pack && mkdir -p .pack && pnpm pack --pack-destination .pack --json && pnpm check:package-contents && tsx scripts/smoke-tarball.ts","typecheck:types":"pnpm test:type","test:diagnostics":"tsx scripts/check-diagnostics.ts","release:preflight":"pnpm check && pnpm bench:types && pnpm bench:native:check:only && pnpm pack:check:only && pnpm audit --prod && pnpm check:zero-runtime-deps","test:examples:run":"tsc -p tsconfig.examples.json --noEmit && tsx scripts/run-examples.ts","bench:native:check":"pnpm build && pnpm bench:native:check:only","check:architecture":"tsx scripts/check-architecture.ts","release:verify-tag":"tsx scripts/verify-release-tag.ts","test:temporal-real":"vitest run tests/integration/temporal-real.test.mjs","typecheck:benchmarks":"tsc -p tsconfig.benchmarks.package.json --noEmit && tsc -p tsconfig.benchmarks.dispatch.json --noEmit","smoke:package-manager":"tsx scripts/smoke-package-manager.ts","test:temporal-browser":"pnpm build && node scripts/check-browser-temporal.mjs","check:package-contents":"tsx scripts/check-package-contents.ts","test:examples:validate":"tsx scripts/validate-examples.ts","bench:native:check:only":"tsx scripts/check-benchmark-budgets.ts","check:zero-runtime-deps":"tsx scripts/check-zero-runtime-deps.ts","release:verify-unpublished":"tsx scripts/verify-npm-version-unpublished.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:dba2a1ac-602d-4b63-9c89-cacbc92d06a6"}},"_resolved":"/home/runner/work/ts-match/ts-match/.pack/diegogbrisa-ts-match-1.6.1.tgz","_integrity":"sha512-CJCALxChEbr8gCmdAPHOQv0kilTfrRfAGwg8MS64iIO/vWPBBvQQ2qyk3pb7xosUelkmdLCRD+zJvWkjGJEq/A==","repository":{"url":"git+https://github.com/DiegoGBrisa/ts-match.git","type":"git"},"_npmVersion":"11.13.0","description":"TypeScript-first pattern matching with matchBy ergonomics, exhaustive checks, and zero runtime dependencies.","directories":{},"sideEffects":false,"_nodeVersion":"24.16.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"latest","eslint":"^10.2.1","vitest":"latest","prettier":"^3.8.3","playwright":"^1.60.0","ts-pattern":"^5.9.0","typescript":"latest","@types/node":"latest","typescript-eslint":"^8.59.1","@vitest/coverage-v8":"^4.1.5","eslint-plugin-import-x":"^4.16.2","eslint-import-resolver-typescript":"^4.4.5"},"_npmOperationalInternal":{"tmp":"tmp/ts-match_1.6.1_1781207616082_0.575002092213958","host":"s3://npm-registry-packages-npm-production"}},"1.6.2":{"name":"@diegogbrisa/ts-match","version":"1.6.2","description":"TypeScript-first pattern matching with matchBy ergonomics, exhaustive checks, and zero runtime dependencies.","type":"module","license":"MIT","repository":{"type":"git","url":"git+https://github.com/DiegoGBrisa/ts-match.git"},"keywords":["typescript","pattern-matching","exhaustive","match","discriminated-union","discriminated-unions","assert-never","type-safety","reducer","union"],"publishConfig":{"access":"public"},"sideEffects":false,"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist-cjs/index.js"},"./assertions":{"types":"./dist/assertions/index.d.ts","import":"./dist/assertions/index.js","require":"./dist-cjs/assertions/index.js"},"./errors":{"types":"./dist/errors/index.d.ts","import":"./dist/errors/index.js","require":"./dist-cjs/errors/index.js"},"./group":{"types":"./dist/group/index.d.ts","import":"./dist/group/index.js","require":"./dist-cjs/group/index.js"},"./match":{"types":"./dist/match/index.d.ts","import":"./dist/match/index.js","require":"./dist-cjs/match/index.js"},"./match-by":{"types":"./dist/match-by/index.d.ts","import":"./dist/match-by/index.js","require":"./dist-cjs/match-by/index.js"},"./patterns":{"types":"./dist/patterns/index.d.ts","import":"./dist/patterns/index.js","require":"./dist-cjs/patterns/index.js"}},"types":"./dist/index.d.ts","devDependencies":{"@types/node":"latest","@vitest/coverage-v8":"^4.1.5","eslint":"^10.2.1","eslint-import-resolver-typescript":"^4.4.5","eslint-plugin-import-x":"^4.16.2","playwright":"^1.60.0","prettier":"^3.8.3","ts-pattern":"^5.9.0","tsx":"latest","typescript":"latest","typescript-eslint":"^8.59.1","vitest":"latest"},"engines":{"node":">=20"},"scripts":{"build":"pnpm clean && tsc -p tsconfig.build.json && tsc -p tsconfig.cjs.json && tsx scripts/write-cjs-package-json.ts","clean":"rm -rf dist dist-cjs","test":"vitest run","test:editor-dx":"vitest run src/**/__tests__/*editor-dx.test.ts","test:coverage":"vitest run --config vitest.coverage.config.ts --coverage","test:type":"tsc -p tsconfig.type-tests.json --noEmit","test:diagnostics":"tsx scripts/check-diagnostics.ts","test:temporal-real":"vitest run tests/integration/temporal-real.test.mjs","test:temporal-browser":"pnpm build && node scripts/check-browser-temporal.mjs","typecheck":"pnpm build && pnpm typecheck:only && pnpm typecheck:benchmarks","typecheck:only":"tsc -p tsconfig.json --noEmit","typecheck:benchmarks":"tsc -p tsconfig.benchmarks.package.json --noEmit && tsc -p tsconfig.benchmarks.dispatch.json --noEmit","typecheck:types":"pnpm test:type","lint":"pnpm build && pnpm lint:only","lint:only":"eslint \"**/*.ts\"","lint:fix":"pnpm build && eslint \"**/*.ts\" --fix","format":"prettier . --write","format:check":"prettier . --check","smoke:exports":"tsx scripts/smoke-exports.ts","smoke:package-manager":"tsx scripts/smoke-package-manager.ts","check:commits":"tsx scripts/check-conventional-commits.ts","check:zero-runtime-deps":"tsx scripts/check-zero-runtime-deps.ts","check:package-contents":"tsx scripts/check-package-contents.ts","test:docs":"tsx scripts/validate-docs.ts","test:examples":"pnpm build && pnpm test:examples:validate && pnpm test:examples:run","test:examples:validate":"tsx scripts/validate-examples.ts","test:examples:run":"tsc -p tsconfig.examples.json --noEmit && tsx scripts/run-examples.ts","check":"pnpm check:architecture && pnpm format:check && pnpm build && pnpm lint:only && pnpm typecheck:only && pnpm typecheck:benchmarks && pnpm test:type && pnpm test:diagnostics && pnpm test:editor-dx && pnpm test:coverage && pnpm smoke:exports && pnpm test:docs && pnpm test:examples:validate && pnpm test:examples:run","check:architecture":"tsx scripts/check-architecture.ts","bench:native":"pnpm build && tsx benchmarks/native.ts","bench:native:check":"pnpm build && pnpm bench:native:check:only","bench:native:check:only":"tsx scripts/check-benchmark-budgets.ts","bench:dispatch":"tsx benchmarks/dispatch.ts","bench:compare":"pnpm build && tsx benchmarks/compare-ts-pattern.ts","bench:types":"tsc -p tsconfig.type-bench.json --noEmit --extendedDiagnostics","pack:check":"pnpm build && pnpm pack:check:only","pack:check:only":"rm -rf .pack && mkdir -p .pack && pnpm pack --pack-destination .pack --json && pnpm check:package-contents && tsx scripts/smoke-tarball.ts","release:notes":"tsx scripts/extract-release-notes.ts","release:preflight":"pnpm check && pnpm bench:types && pnpm bench:native:check:only && pnpm pack:check:only && pnpm audit --prod && pnpm check:zero-runtime-deps","release:verify-tag":"tsx scripts/verify-release-tag.ts","release:verify-unpublished":"tsx scripts/verify-npm-version-unpublished.ts"},"_id":"@diegogbrisa/ts-match@1.6.2","bugs":{"url":"https://github.com/DiegoGBrisa/ts-match/issues"},"homepage":"https://github.com/DiegoGBrisa/ts-match#readme","_integrity":"sha512-RXCs8qA6CfkWUZw9ZIPkclE3Nqq9p66Munmml6fBSs2Yg4SnZzqXGk/HeiIvqHPi/sY2N9gLcxuWmebYLi71yg==","_resolved":"/home/runner/work/ts-match/ts-match/.pack/diegogbrisa-ts-match-1.6.2.tgz","_from":"file:.pack/diegogbrisa-ts-match-1.6.2.tgz","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-RXCs8qA6CfkWUZw9ZIPkclE3Nqq9p66Munmml6fBSs2Yg4SnZzqXGk/HeiIvqHPi/sY2N9gLcxuWmebYLi71yg==","shasum":"c150b1feddd54bbbeb3718ea046632601fecca6d","tarball":"https://registry.npmjs.org/@diegogbrisa/ts-match/-/ts-match-1.6.2.tgz","fileCount":195,"unpackedSize":724285,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@diegogbrisa%2fts-match@1.6.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCmRjbrhS/hx+MiCD71QD3JAtojYzTyijuPCPLV5QhgfgIgY0gR04iL5uRMZmjHLKCWQSdHXkDevokmS8zcFKgaZlk="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:dba2a1ac-602d-4b63-9c89-cacbc92d06a6"}},"directories":{},"maintainers":[{"name":"diegog_08","email":"d.garciabrisa@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ts-match_1.6.2_1783761302591_0.08157015610594831"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-29T12:17:43.486Z","modified":"2026-07-11T09:15:03.057Z","1.0.0":"2026-04-29T12:17:43.789Z","1.0.2":"2026-04-30T08:35:07.526Z","1.0.3":"2026-04-30T08:44:46.811Z","1.1.0":"2026-04-30T18:35:53.367Z","1.2.0":"2026-05-04T08:46:05.922Z","1.3.0":"2026-06-04T11:32:26.338Z","1.4.0":"2026-06-05T07:35:04.910Z","1.5.0":"2026-06-09T07:45:14.479Z","1.6.0":"2026-06-11T09:27:06.767Z","1.6.1":"2026-06-11T19:53:36.223Z","1.6.2":"2026-07-11T09:15:02.762Z"},"bugs":{"url":"https://github.com/DiegoGBrisa/ts-match/issues"},"license":"MIT","homepage":"https://github.com/DiegoGBrisa/ts-match#readme","keywords":["typescript","pattern-matching","exhaustive","match","discriminated-union","discriminated-unions","assert-never","type-safety","reducer","union"],"repository":{"type":"git","url":"git+https://github.com/DiegoGBrisa/ts-match.git"},"description":"TypeScript-first pattern matching with matchBy ergonomics, exhaustive checks, and zero runtime dependencies.","maintainers":[{"name":"diegog_08","email":"d.garciabrisa@gmail.com"}],"readme":"# ts-match\n\n[![npm version](https://img.shields.io/npm/v/%40diegogbrisa%2Fts-match.svg)](https://www.npmjs.com/package/@diegogbrisa/ts-match)\n\n**Exhaustive matching for TypeScript discriminated unions** — with ergonomic `matchBy(...)`, strong inference, structural patterns when you need them, and zero runtime dependencies.\n\n## Installation\n\n```bash\nnpm install @diegogbrisa/ts-match\npnpm add @diegogbrisa/ts-match\nyarn add @diegogbrisa/ts-match\nbun add @diegogbrisa/ts-match\n```\n\n`ts-match` is built for the kind of TypeScript branching that gets ugly fast:\n\n- reducers and event routers\n- UI state handling\n- API result unions\n- nested object/tuple matching when `switch` stops being enough\n\n```ts\nimport { matchBy } from '@diegogbrisa/ts-match'\n\ntype CartAction =\n  | { type: 'addItem'; sku: string; quantity: number }\n  | { type: 'applyCoupon'; code: string; percentOff: number }\n  | { type: 'clearCart'; reason: 'user' | 'timeout' }\n\nfunction planCartOperation(action: CartAction) {\n  return matchBy(action, 'type')\n    .with('addItem', (action) => ({ type: 'lineItemAdded', sku: action.sku, quantity: action.quantity }))\n    .with('applyCoupon', (action) => ({\n      type: 'discountApplied',\n      code: action.code,\n      multiplier: 1 - action.percentOff / 100,\n    }))\n    .with('clearCart', (action) => ({ type: 'cartCleared', reason: action.reason }))\n    .exhaustive()\n}\n```\n\n## Why developers reach for `ts-match`\n\n- **Exhaustive discriminated-union handling** without hand-rolled `assertNever` helpers.\n- **Narrowed handler parameters** without manual casts.\n- **`matchBy(value, 'type')` ergonomics** for the most common TypeScript branching style.\n- **Structural patterns** for objects, tuples, arrays, and records when plain `switch` is not expressive enough.\n- **Promise-aware matching** through `match.promise` and `matchBy.promise`.\n- **Runtime validation helpers** with `isMatching` and `assertMatching`.\n- **Zero runtime dependencies** and a small surface for production use.\n\n## Why not just use `switch`?\n\n`switch` is still great for simple branching. `ts-match` becomes useful when your code also needs:\n\n- exhaustiveness over closed unions;\n- narrowed branch-local payload types;\n- nested object or tuple matching;\n- reusable runtime pattern helpers;\n- cleaner reducer / event-dispatch ergonomics.\n\nIf a normal `if` or `switch` is already the clearest tool, use it. The point of `ts-match` is to make the harder branching cases cleaner, not to replace every conditional.\n\n## Before / after\n\n### Plain `switch`\n\n```ts\nfunction planCartOperation(action: CartAction) {\n  switch (action.type) {\n    case 'addItem':\n      return { type: 'lineItemAdded', sku: action.sku, quantity: action.quantity }\n    case 'applyCoupon':\n      return {\n        type: 'discountApplied',\n        code: action.code,\n        multiplier: 1 - action.percentOff / 100,\n      }\n    case 'clearCart':\n      return { type: 'cartCleared', reason: action.reason }\n    default: {\n      const _never: never = action\n      return _never\n    }\n  }\n}\n```\n\n### `ts-match`\n\n```ts\nfunction planCartOperation(action: CartAction) {\n  return matchBy(action, 'type')\n    .with('addItem', (action) => ({ type: 'lineItemAdded', sku: action.sku, quantity: action.quantity }))\n    .with('applyCoupon', (action) => ({\n      type: 'discountApplied',\n      code: action.code,\n      multiplier: 1 - action.percentOff / 100,\n    }))\n    .with('clearCart', (action) => ({ type: 'cartCleared', reason: action.reason }))\n    .exhaustive()\n}\n```\n\n## When to use it\n\nReach for `ts-match` when you want:\n\n- a clean exhaustive reducer or event router;\n- safer handling of discriminated unions;\n- structural matching beyond one-key dispatch;\n- typed runtime validation helpers in the same toolkit.\n\nYou may not need it when your branch is already trivial and a normal condition reads better.\n\n## Quick reasons to evaluate it over alternatives\n\n- Strong focus on **TypeScript-first discriminant dispatch** via `matchBy(...)`.\n- Includes both **ergonomic application-style branching** and **deeper structural matching**.\n- Designed to stay honest about tradeoffs: simple branches should stay simple.\n\n## Documentation\n\n- [Quick start](#quick-start)\n- [Why pattern matching?](#why-use-pattern-matching-instead-of-manual-branching)\n- [Core concepts](#core-concepts)\n- [Imports and entrypoints](#imports-and-package-entrypoints)\n- API\n  - [`match`](#match)\n  - [`match.promise`](#matchpromise)\n  - [`matchBy`](#matchby)\n  - [`matchBy.promise`](#matchbypromise)\n  - [`group`](#group)\n  - [`P` patterns](#pattern-guide-p-namespace)\n  - [Named `p*` helpers](#named-p-helper-exports)\n  - [`isMatching`](#ismatching)\n  - [`assertMatching`](#assertmatching)\n  - [Errors](#error-classes)\n- TypeScript\n  - [Inference guide](#typescript-inference-guide)\n  - [Diagnostics and troubleshooting](#typescript-diagnostics-and-troubleshooting)\n- [Performance guide](#performance-guide)\n- [Limitations and tradeoffs](#limitations-and-tradeoffs)\n- [Examples index](#full-examples-index)\n- [API summary](#api-reference-summary)\n- [Acknowledgements](#acknowledgements)\n- [Agent skill](SKILL.md)\n\n## Quick start\n\nUse `matchBy(value, path)` for discriminated unions when one key decides the branch and handlers still need the full narrowed value.\n\n```ts\nimport { matchBy } from '@diegogbrisa/ts-match'\n\ntype State =\n  | { status: 'idle'; rows: readonly string[] }\n  | { status: 'loading'; rows: readonly string[] }\n  | { status: 'ready'; rows: readonly string[] }\n  | { status: 'failed'; message: string }\n\ntype Action =\n  | { type: 'start-loading' }\n  | { type: 'load-success'; rows: readonly string[] }\n  | { type: 'load-failure'; message: string }\n  | { type: 'clear' }\n\nfunction reduce(state: State, action: Action) {\n  const rows = 'rows' in state ? state.rows : []\n\n  return matchBy(action, 'type')\n    .with('start-loading', () => ({ status: 'loading', rows }))\n    .with('load-success', (action) => ({ status: 'ready', rows: action.rows }))\n    .with('load-failure', (action) => ({ status: 'failed', message: action.message }))\n    .with('clear', () => ({ status: 'idle', rows: [] }))\n    .exhaustive()\n}\n\nconst next = reduce({ status: 'idle', rows: [] }, { type: 'load-success', rows: ['Ada', 'Grace'] })\n```\n\nChecked example: [`examples/02-exhaustive-discriminated-union.ts`](examples/02-exhaustive-discriminated-union.ts) — exhaustive reducer branching for a TypeScript discriminated union.\n\n## Why use pattern matching instead of manual branching?\n\nManual `if`/`else` or `switch` branches work, but domain logic often needs more than a single equality check:\n\n- exhaustive handling for closed unions;\n- narrowed handler parameters without manual casts;\n- nested object, tuple, array, and record patterns;\n- selected values passed directly to handlers;\n- reusable runtime validators through `isMatching` and `assertMatching`;\n- promise-aware matching with `match.promise` and `matchBy.promise`.\n\nUse this library where those constraints make code clearer. Keep simple branches simple when a normal condition is already the clearest tool.\n\n## Core concepts\n\n- **Value** — the input passed to `match(value)` or `matchBy(value, path)`.\n- **Pattern** — a literal, object pattern, tuple pattern, or `P` helper that decides whether a branch matches.\n- **Handler** — the function called for the first matching branch. Its parameter is narrowed from the matched pattern.\n- **Exhaustiveness** — `.exhaustive()` is callable only when TypeScript can prove no variants remain. At runtime it throws `NonExhaustiveMatchError` if unexpected data reaches it.\n- **Fallback** — `.otherwise(handler)` handles the remaining value instead of requiring exhaustiveness.\n- **Sync vs promise** — `match(...)` and `matchBy(...)` are synchronous. Use `match.promise(...)` and `matchBy.promise(...)` when the source may be promise-backed or when the terminal result should be a promise. Promise builders resolve the input internally and handlers receive the resolved value.\n- **`P` vs `p*` helpers** — `P.string` and `pString` are the same pattern helper exposed in namespace and named-import form.\n\n## Imports and package entrypoints\n\nInstall and import from the published package name, `@diegogbrisa/ts-match`. Root imports cover normal usage:\n\n```ts\nimport { assertMatching, group, isMatching, match, matchBy, P } from '@diegogbrisa/ts-match'\n```\n\nFocused subpath imports are available:\n\n```ts\nimport { match } from '@diegogbrisa/ts-match/match'\nimport { matchBy } from '@diegogbrisa/ts-match/match-by'\nimport { P, pString } from '@diegogbrisa/ts-match/patterns'\nimport { isMatching } from '@diegogbrisa/ts-match/assertions'\nimport { NonExhaustiveMatchError } from '@diegogbrisa/ts-match/errors'\nimport { group } from '@diegogbrisa/ts-match/group'\n```\n\nThere is no default export.\n\n## `match`\n\n`match(value)` checks patterns in order. The first matching branch wins.\n\n```ts\nimport { match, P } from '@diegogbrisa/ts-match'\n\nconst pageUrl = new URL('https://shop.example/products?view=grid&coupon=SPRING')\nconst view = pageUrl.searchParams.get('view')\n\nconst layout = match(view)\n  .with('grid', () => ({ columns: 3 }))\n  .with('list', () => ({ columns: 1 }))\n  .with(P.null, () => ({ columns: 2 }))\n  .otherwise(() => ({ columns: 2 }))\n```\n\nChecked example: [`examples/01-basic-match.ts`](examples/01-basic-match.ts) — basic TypeScript pattern matching.\n\n### `.with(pattern, handler)`\n\nUse one pattern per branch for most code:\n\n```ts\nconst result = match(response)\n  .with({ ok: true }, (value) => value.body)\n  .with({ ok: false }, (value) => value.message)\n  .exhaustive()\n```\n\nHandlers receive the matched/narrowed value unless the pattern contains selections. Multiple patterns can share one handler:\n\n```ts\nconst status = match(state)\n  .with('idle', 'loading', () => 'pending')\n  .with('success', () => 'done')\n  .exhaustive()\n```\n\n### `.when(predicate, handler)`\n\nUse `.when(...)` for value-level predicates:\n\n```ts\nfunction discountLabel(percent: number) {\n  return match(percent)\n    .when(\n      (value) => value > 0,\n      (value) => `${String(value)}% off`,\n    )\n    .otherwise(() => 'No discount')\n}\n```\n\n`P.when(predicate)` is the pattern-helper form and can be nested inside object/tuple patterns.\n\n### `.otherwise(handler)`\n\nUse `.otherwise(...)` when the input is open-ended or a fallback is intended. The handler receives the remaining value type.\n\n### `.exhaustive()`\n\nUse `.exhaustive()` for closed unions. It returns the union of branch return types. TypeScript rejects it while variants remain unhandled.\n\nRuntime error: `NonExhaustiveMatchError` if unexpected data reaches the terminal at runtime.\n\n### Rendering UI from typed data\n\nA match expression returns whatever its handler returns, so JSX can be the result of a branch. This is useful for UI states where the data shape decides what should be rendered:\n\n```tsx\nimport { match, P } from '@diegogbrisa/ts-match'\n\ntype ProductContent = { type: 'text'; body: string } | { type: 'image'; src: string; alt: string }\n\ntype ProductResult =\n  | { status: 'loading' }\n  | { status: 'success'; product: { title: string; content: ProductContent } }\n  | { status: 'error'; error: Error }\n\nfunction ProductPreview({ result }: { result: ProductResult }) {\n  return match(result)\n    .with({ status: 'loading' }, () => <p>Loading product…</p>)\n    .with({ status: 'error' }, ({ error }) => <p role=\"alert\">{error.message}</p>)\n    .with({ status: 'success', product: { content: { type: 'text' } } }, ({ product }) => (\n      <article>\n        <h2>{product.title}</h2>\n        <p>{product.content.body}</p>\n      </article>\n    ))\n    .with(\n      { status: 'success', product: { content: { type: 'image', src: P.select('src'), alt: P.select('alt') } } },\n      ({ src, alt }) => <img src={src} alt={alt} />,\n    )\n    .exhaustive()\n}\n```\n\n`ts-match` is framework-agnostic; React is just a familiar way to show that handlers can return UI, objects, strings, promises, or whatever type your branch needs.\n\n## `match.promise`\n\n`match.promise(valueOrPromise)` has the same branch API as `match(value)`, but it resolves the input internally and terminal methods return promises:\n\n```ts\ntype ProfileResponse =\n  | { ok: true; profile: { id: string; name: string } }\n  | { ok: false; status: number; message: string }\n\nconst profileResponse: ProfileResponse = { ok: true, profile: { id: 'user-1', name: 'Ada' } }\nconst missingProfile: ProfileResponse = { ok: false, status: 404, message: 'missing' }\nconst responses: readonly ProfileResponse[] = [profileResponse, missingProfile]\nconst profilePromise = Promise.resolve(responses[0] ?? missingProfile)\n\nconst profileName = await match\n  .promise(profilePromise)\n  .with({ ok: true, profile: { name: P.select('name', P.string) } }, ({ name }) => name)\n  .with({ ok: false }, ({ status, message }) => `Request failed (${String(status)}): ${message}`)\n  .exhaustive()\n```\n\nChecked example: [`examples/03-match-promise.ts`](examples/03-match-promise.ts).\n\nBehavior:\n\n- accepts values, promises, thenables, and `PromiseLike` inputs;\n- handlers receive `Awaited<TInput>`, not the promise wrapper;\n- handler values and promise-like values are awaited by the terminal promise;\n- synchronous handler throws, predicate throws, pattern errors, and input rejections become promise rejections for normal terminals;\n- `.otherwise(...)` is a pattern fallback, not an input-error fallback;\n- `.otherwise(...)` and `.exhaustive()` return `Promise<...>`.\n\nPromise builders also expose safe terminals:\n\n```ts\nconst missingProfile: ProfileResponse = { ok: false, status: 404, message: 'missing' }\nconst missingResponses: readonly ProfileResponse[] = [missingProfile]\nconst missingProfilePromise = Promise.resolve(missingResponses[0] ?? missingProfile)\n\nconst result = await match\n  .promise(missingProfilePromise)\n  .with({ ok: true, profile: { name: P.select('name', P.string) } }, ({ name }) => name)\n  .safeOtherwise(() => 'Guest')\n\nif (result.ok) {\n  result.value\n} else {\n  result.error\n}\n```\n\n- `.safeExhaustive()` preserves the same compile-time exhaustiveness check as `.exhaustive()`.\n- `.safeOtherwise(handler)` requires a fallback handler.\n- Safe terminals resolve to `{ ok: true, value } | { ok: false, error }` and catch input, pattern, predicate, handler, fallback, and defensive non-exhaustive failures.\n\nUse `safeExhaustive()` when all variants should be handled but operational failures should be values:\n\n```ts\nconst result = await match\n  .promise(profilePromise)\n  .with({ ok: true }, ({ profile }) => profile.name)\n  .with({ ok: false }, ({ message }) => message)\n  .safeExhaustive()\n```\n\nUse sync `match(promise)` only if you intentionally want to pattern-match the `Promise` object itself.\n\n## `matchBy`\n\n`matchBy(value, path)` is specialized for discriminant dispatch. It reads a path, matches tags, and passes the full narrowed value to handlers.\n\n### Direct key\n\n```ts\nfunction planCartOperation(action: CartAction) {\n  return matchBy(action, 'type')\n    .with('addItem', (value) => ({ type: 'lineItemAdded', sku: value.sku, quantity: value.quantity }))\n    .with('applyCoupon', (value) => ({\n      type: 'discountApplied',\n      code: value.code,\n      multiplier: 1 - value.percentOff / 100,\n    }))\n    .with('clearCart', (value) => ({ type: 'cartCleared', reason: value.reason }))\n    .exhaustive()\n}\n```\n\nChecked example: [`examples/04-match-by-direct-key.ts`](examples/04-match-by-direct-key.ts).\n\n### Nested dot path and tuple path\n\nDot paths read nested string-key properties and autocomplete finite tag-like paths from the input value type. Tuple paths provide segment-by-segment autocomplete and are useful for symbols and exact path segments.\n\n```ts\nconst EVENT_KIND = Symbol('event-kind')\n\ntype UiEvent = { meta: { type: 'click'; x: number; y: number } } | { meta: { type: 'submit'; form: string } }\n\ntype SourceEvent = { meta: { [EVENT_KIND]: 'user'; name: string } } | { meta: { [EVENT_KIND]: 'system'; code: number } }\n\nfunction routeEvent(event: UiEvent) {\n  return matchBy(event, 'meta.type')\n    .with('click', (value) => ({ kind: 'pointer', x: value.meta.x, y: value.meta.y }))\n    .with('submit', (value) => ({ kind: 'form', form: value.meta.form }))\n    .exhaustive()\n}\n\nfunction labelSource(event: SourceEvent) {\n  return matchBy(event, ['meta', EVENT_KIND])\n    .with('user', (value) => `User: ${value.meta.name}`)\n    .with('system', (value) => `System: ${String(value.meta.code)}`)\n    .exhaustive()\n}\n```\n\nChecked example: [`examples/05-match-by-nested-path.ts`](examples/05-match-by-nested-path.ts).\n\nAutocomplete intentionally suggests finite tag-like paths, such as literal string/number/boolean unions. Broad payload leaves such as `number` coordinates or arbitrary `string` labels can still be typed manually when you want fallback-based matching, but they are not suggested as primary discriminant paths.\n\nDot-path limitation: a dot string always means nesting. Use tuple paths for literal keys that contain dots.\n\n### `.cases(...)`\n\n`.cases(...)` is an exhaustive terminal for `matchBy`. It supports three input shapes.\n\nQuick choice guide:\n\n- Use chained `.with(...).exhaustive()` as the default for application code. It has the clearest control flow, strong local inference, and no inline case-map allocation.\n- Use inline `.cases({...})` when a compact object-map style reads best and the code is not in a hot loop.\n- Use hoisted `.cases(caseMap)` for hot discriminant-dispatch paths where throughput matters more than annotation-free handler inference.\n- Use callback grouped cases when several tags share a handler and you want the best local inference.\n- Use tuple/grouped entry arrays for generated cases, non-object-key tags, `null`/`undefined`, or normalized key collisions such as `1` and `'1'`.\n\n#### Object case maps\n\nObject-map cases are exhaustive and exact for finite discriminants representable as object keys. They support string, number, symbol, and boolean tags when the normalized object keys do not collide.\n\n```ts\nfunction auditCartAction(action: CartAction) {\n  return matchBy(action, 'type').cases({\n    addItem: (value) => ({ category: 'inventory', sku: value.sku, quantity: value.quantity }),\n    applyCoupon: (value) => ({ category: 'pricing', code: value.code, percentOff: value.percentOff }),\n    clearCart: (value) => ({ category: 'lifecycle', reason: value.reason }),\n  })\n}\n```\n\nUse object-map cases when you want compact map-style DX in ordinary non-hot code. Avoid recreating inline case maps inside tight loops: fresh maps allocate handlers/maps and go through validation each time. In local benchmark runs, hoisted object maps are roughly 15x faster than inline object maps for discriminant dispatch, and about 4x faster than chained `.with(...).exhaustive()` dispatch. The exact ratio depends on runtime and workload, but the direction is consistent: hoist maps in hot paths, keep inline maps for ordinary readability.\n\n```ts\n// Inline: concise, but recreates the map and handlers on every call.\nfunction auditCartAction(action: CartAction) {\n  return matchBy(action, 'type').cases({\n    addItem: (value) => value.sku,\n    applyCoupon: (value) => value.code,\n    clearCart: (value) => value.reason,\n  })\n}\n\n// Hoisted: fastest measured discriminant-dispatch shape, but handlers may need annotations.\nconst cartAuditCases = {\n  addItem: (value: Extract<CartAction, { type: 'addItem' }>) => value.sku,\n  applyCoupon: (value: Extract<CartAction, { type: 'applyCoupon' }>) => value.code,\n  clearCart: (value: Extract<CartAction, { type: 'clearCart' }>) => value.reason,\n}\n\nfunction auditCartActionHot(action: CartAction) {\n  return matchBy(action, 'type').cases(cartAuditCases)\n}\n```\n\nThe benchmark suite currently shows hoisted object maps as the fastest measured `ts-match` discriminant-dispatch shape, but hoisting removes contextual handler inference and can require manual handler parameter types. For JavaScript-feeling TypeScript, prefer `.with(...).exhaustive()` unless you deliberately choose that tradeoff.\n\nUse grouped/callback cases for `null`, `undefined`, or collisions such as `1` and `'1'`. Avoid bare `__proto__:` object-literal syntax because JavaScript treats it specially; use computed `['__proto__']`, tuple entries, or grouped cases when that tag matters.\n\n#### Callback grouped cases\n\nCallback grouped cases preserve local handler inference and support every discriminant value including `null` and `undefined`. Use them with exhaustive `.cases(...)` or non-exhaustive `.partial(...).otherwise(...)`:\n\n```ts\ntype SessionEvent =\n  | { type: 'start'; at: number }\n  | { type: 'resume'; at: number }\n  | { type: 'stop'; reason: string }\n  | { type: 'error'; message: string }\n\nfunction sessionStatus(event: SessionEvent) {\n  return matchBy(event, 'type').cases((group) => [\n    group('start', 'resume', (value) => ({ status: 'active', at: value.at })),\n    group('stop', (value) => ({ status: 'stopped', reason: value.reason })),\n    group('error', (value) => ({ status: 'failed', message: value.message })),\n  ])\n}\n```\n\nUse this form when multiple tags share one handler and you want annotation-free narrowed parameters. Use variadic tags (`group('a', 'b', handler)`) while writing inline groups because that shape gives the best tag autocomplete. Array tags (`group(['a', 'b'], handler)`) are also supported without `as const` and can read better when the tags belong together, but editors may not suggest tag literals inside that nested array. The same callback-local `group` helper is available in `.partial((group) => [...])` when the remaining tags should fall through to `.otherwise(...)`.\n\n#### Tuple and grouped entry arrays\n\nEntry arrays are exhaustive and useful when cases are generated, reordered, or easier to express as tuples:\n\n```ts\ntype State =\n  | { kind: 'ready'; data: string }\n  | { kind: 'failed'; reason: string }\n  | { kind: null }\n  | { kind?: undefined }\n\ndeclare const state: State\n\nconst label = matchBy(state, 'kind').cases([\n  ['ready', (value) => value.data],\n  [[null, undefined], () => 'empty'],\n  ['failed', (value) => value.reason],\n])\n```\n\nValid entry shapes are:\n\n- `[tag, handler]` for one tag;\n- `[[tag1, tag2], handler]` for a static group;\n- `group(tag, handler)`, `group(tag1, tag2, ...moreTags, handler)`, or `group(tags, handler)` for reusable grouped entries.\n\nInline tuple-entry arrays contextually infer handlers from their sibling tags. Partial grouped arrays preserve tag autocomplete while editing grouped tags. Exhaustive grouped `.cases([...])` keeps missing-case diagnostics active while the list is incomplete, so callback `.cases((group) => [group('a', 'b', handler)])` is the best autocomplete shape for grouped exhaustive cases. Broad runtime arrays are accepted at runtime but cannot prove exhaustive coverage because TypeScript cannot know which tags they contain. Exported `group(...)` entries are useful for reusable structures but can need explicit handler parameter annotations; use callback `.cases((group) => [...])` or `.partial((group) => [...])` when you want grouped entries with the strongest annotation-free handler inference.\n\n### `.with(...tags, handler)`\n\nUse `.with` to chain tag groups before a final `.exhaustive()` or `.otherwise(...)`:\n\n```ts\ntype ConnectionEvent = { type: 'start'; id: string } | { type: 'resume'; id: string } | { type: 'stop'; reason: string }\n\nfunction connectionLabel(event: ConnectionEvent) {\n  return matchBy(event, 'type')\n    .with('start', 'resume', (value) => `active:${value.id}`)\n    .with('stop', (value) => `stopped:${value.reason}`)\n    .exhaustive()\n}\n```\n\nChecked example: [`examples/15-match-by-with-partial.ts`](examples/15-match-by-with-partial.ts).\n\n### `.partial(...).otherwise(...)`\n\nUse `.partial(...)` when only some tags need special handling and the rest should go to `.otherwise(...)`. It accepts the same object-map and tuple/grouped entry shapes as `.cases(...)`, but it is intentionally non-exhaustive.\n\nObject-map partial:\n\n```ts\ntype CartAction =\n  | { type: 'addItem'; cartId: string; sku: string; quantity: number }\n  | { type: 'updateQuantity'; cartId: string; sku: string; quantity: number }\n  | { type: 'applyCoupon'; cartId: string; code: string }\n  | { type: 'checkout'; cartId: string; total: number }\n  | { type: 'noop' }\n\nfunction cartResponse(action: CartAction) {\n  return matchBy(action, 'type')\n    .partial({\n      checkout: (value) => ({ screen: 'payment', cartId: value.cartId, total: value.total }),\n    })\n    .otherwise(() => ({ screen: 'cart' }))\n}\n```\n\nTuple/grouped-entry partial:\n\n```ts\nfunction cartReview(action: CartAction) {\n  return matchBy(action, 'type')\n    .partial([\n      [\n        ['addItem', 'updateQuantity'],\n        (value) => ({ type: 'inventoryCheck', sku: value.sku, quantity: value.quantity }),\n      ],\n      ['applyCoupon', (value) => ({ type: 'discountPreview', cartId: value.cartId, code: value.code })],\n    ])\n    .otherwise(() => ({ type: 'noReview' }))\n}\n```\n\nCallback grouped partials are also supported when shared handlers read better with a local `group` helper:\n\n```ts\nfunction cartReviewWithGroups(action: CartAction) {\n  return matchBy(action, 'type')\n    .partial((group) => [\n      group('addItem', 'updateQuantity', (value) => ({\n        type: 'inventoryCheck',\n        sku: value.sku,\n        quantity: value.quantity,\n      })),\n    ])\n    .otherwise(() => ({ type: 'noReview' }))\n}\n```\n\nChecked example: [`examples/15-match-by-with-partial.ts`](examples/15-match-by-with-partial.ts).\n\n### Runtime behavior\n\nIf no `matchBy` case matches, `cases(...)` and `.exhaustive()` throw `NonExhaustiveMatchError` with `matcher`, `path`, `tag`, and `valuePreview` metadata where available. If a path segment is missing, the selected tag is `undefined`; handle it with tuple or grouped entries when that is a valid runtime state.\n\n## `matchBy.promise`\n\n`matchBy.promise(valueOrPromise, path)` resolves the input internally, then performs the same path/tag dispatch as `matchBy(value, path)`. Pass the promise directly; handlers receive the resolved value.\n\n```ts\ntype Order =\n  | { state: 'pending'; id: string; total: number }\n  | { state: 'paid'; id: string; total: number; receiptUrl: string }\n  | { state: 'shipped'; id: string; trackingNumber: string }\n  | { state: 'cancelled'; id: string; reason: string }\n\nconst orders: readonly Order[] = [\n  { state: 'paid', id: 'order-1', total: 49, receiptUrl: '/receipts/order-1' },\n  { state: 'shipped', id: 'order-2', trackingNumber: 'TRACK-2' },\n]\nconst fallbackOrder: Order = { state: 'cancelled', id: 'missing', reason: 'not found' }\n\nasync function fetchOrder(id: string) {\n  return orders.find((order) => order.id === id) ?? fallbackOrder\n}\n\nconst orderView = await matchBy\n  .promise(fetchOrder('order-1'), 'state')\n  .with('pending', (order) => ({ screen: 'checkout', orderId: order.id, total: order.total }))\n  .with('paid', (order) => ({ screen: 'receipt', orderId: order.id, receiptUrl: order.receiptUrl }))\n  .with('shipped', (order) => ({ screen: 'tracking', orderId: order.id, trackingNumber: order.trackingNumber }))\n  .with('cancelled', (order) => {\n    throw new Error(`Order was cancelled: ${order.reason}`)\n  })\n  .exhaustive()\n```\n\nChecked example: [`examples/06-match-by-promise.ts`](examples/06-match-by-promise.ts).\n\nPath, tag, object-map, partial-map, and grouped-case inference all use the resolved input type (`Awaited<TInput>`). That means this keeps the same autocomplete as sync `matchBy(...)` even when the source is a `Promise<Event>` or `Event | PromiseLike<Event>`.\n\nNormal terminals return promises and reject normally for input rejections, path-read errors, handler throws/rejections, fallback throws/rejections, and defensive non-exhaustive failures. `.otherwise(...)` remains only a pattern fallback; it does not catch input promise failures.\n\nSafe terminals mirror `match.promise` and are useful when operational failures should be values:\n\n```ts\nconst result = await matchBy\n  .promise(fetchOrder('order-1'), 'state')\n  .with('cancelled', (order) => ({ screen: 'cancelled', reason: order.reason }))\n  .safeOtherwise((order) => ({ screen: 'order', orderId: order.id }))\n```\n\n- all synchronous `matchBy` case shapes are available on promise builders;\n- `.safeExhaustive()` keeps exhaustive tag checking;\n- `.safeOtherwise(handler)` requires a fallback handler;\n- safe terminals resolve to `{ ok: true, value } | { ok: false, error }`.\n\n## `group`\n\nGrouped cases let several tags share one handler. Prefer the callback form when handlers need inferred narrowed values:\n\n```ts\nconst status = matchBy(event, 'type').cases((group) => [\n  group('start', 'resume', (value) => `active:${value.at}`),\n  group('stop', (value) => `stopped:${value.reason}`),\n  group('error', (value) => `error:${value.message}`),\n])\n```\n\nChecked example: [`examples/07-grouped-cases.ts`](examples/07-grouped-cases.ts).\n\nBoth inline grouped forms are valid:\n\n```ts\ngroup(['start', 'resume'], handler)\ngroup('start', 'resume', handler)\n```\n\nUse the array form when it reads better or when tags are already grouped together. Use the variadic form when the tag list is short and reads naturally inline.\n\nFor exhaustiveness, array-form tags must be statically known. Inline literal arrays count as handled tags; broad runtime arrays such as `readonly ('start' | 'resume')[]` do not prove coverage because TypeScript cannot know which tags are actually present at runtime.\n\nSingle-tag groups do not need a second tag:\n\n```ts\ngroup('stop', (value) => `stopped:${value.reason}`)\n```\n\nVariadic groups can contain two or more tags; the handler is always the final argument:\n\n```ts\ngroup('start', 'resume', 'retry', (value) => `active:${value.at}`)\n```\n\nThe exported `group(...)` helper is useful for reusable prebuilt groups, especially when the handler does not need the narrowed value:\n\n```ts\nimport { group } from '@diegogbrisa/ts-match'\n\nconst reusableStatusCases = [\n  group(['start', 'resume'], () => 'active'),\n  group('stop', () => 'inactive'),\n  group('error', () => 'inactive'),\n]\n```\n\nLimitation: standalone exported `group(...)` is created before `.cases(...)` has context, so TypeScript cannot always infer handler parameter types from the later `matchBy` call. Use `.cases((group) => [...])` for annotation-free handler inference.\n\n## Pattern guide: `P` namespace\n\nImport the namespace when readability is more important than individual helper imports:\n\n```ts\nimport { P } from '@diegogbrisa/ts-match'\n```\n\nChecked example using common helpers: [`examples/08-pattern-helpers.ts`](examples/08-pattern-helpers.ts).\n\n| Helper                                       | What it matches                                  | Notes                                                                                                |\n| -------------------------------------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------- |\n| `P._`                                        | anything                                         | Wildcard. Handler receives the original value.                                                       |\n| `P.any`                                      | anything                                         | Alias of `P._`.                                                                                      |\n| `P.string`                                   | strings                                          | Narrows to `string`.                                                                                 |\n| `P.number`                                   | numbers                                          | Includes `NaN` and infinities; use numeric helpers for stricter checks.                              |\n| `P.boolean`                                  | booleans                                         | Narrows to `boolean`.                                                                                |\n| `P.bigint`                                   | bigints                                          | Narrows to `bigint`.                                                                                 |\n| `P.symbol`                                   | symbols                                          | Narrows to `symbol`.                                                                                 |\n| `P.null`                                     | `null`                                           | Literal null pattern helper.                                                                         |\n| `P.undefined`                                | `undefined`                                      | Literal undefined pattern helper.                                                                    |\n| `P.nan`                                      | `NaN`                                            | Uses `Number.isNaN`.                                                                                 |\n| `P.finite`                                   | finite numbers                                   | Uses `Number.isFinite`.                                                                              |\n| `P.integer`                                  | integers                                         | Uses `Number.isInteger`.                                                                             |\n| `P.regex(regex)`                             | strings accepted by `regex`                      | Requires a `RegExp`; starts at `lastIndex = 0` and restores the original `lastIndex`.                |\n| `P.date`                                     | valid `Date` instances                           | Rejects `Invalid Date`; use `P.instanceOf(Date)` for any `Date` instance.                            |\n| `P.error`                                    | `Error` instances                                | Includes subclasses such as `TypeError` and custom errors.                                           |\n| `P.regexp`                                   | `RegExp` instances                               | Matches regex objects; use `P.regex(regex)` to match strings.                                        |\n| `P.nullish`                                  | `null` or `undefined`                            | Does not match missing object properties unless wrapped in `P.optional(...)`.                        |\n| `P.falsy`                                    | JavaScript-falsy values                          | Matches values where `!value` is true, including `NaN`; broad primitive types narrow conservatively. |\n| `P.truthy`                                   | JavaScript-truthy values                         | Matches values where `Boolean(value)` is true.                                                       |\n| `P.temporal`                                 | any recognized Temporal value object             | Matches nothing when `globalThis.Temporal` is unavailable.                                           |\n| `P.temporalInstant`                          | `Temporal.Instant` instances                     | Uses runtime constructor identity when Temporal is available.                                        |\n| `P.temporalPlainDate`                        | `Temporal.PlainDate` instances                   | Uses runtime constructor identity when Temporal is available.                                        |\n| `P.temporalPlainTime`                        | `Temporal.PlainTime` instances                   | Uses runtime constructor identity when Temporal is available.                                        |\n| `P.temporalPlainDateTime`                    | `Temporal.PlainDateTime` instances               | Uses runtime constructor identity when Temporal is available.                                        |\n| `P.temporalZonedDateTime`                    | `Temporal.ZonedDateTime` instances               | Uses runtime constructor identity when Temporal is available.                                        |\n| `P.temporalDuration`                         | `Temporal.Duration` instances                    | Uses runtime constructor identity when Temporal is available.                                        |\n| `P.temporalPlainYearMonth`                   | `Temporal.PlainYearMonth` instances              | Uses runtime constructor identity when Temporal is available.                                        |\n| `P.temporalPlainMonthDay`                    | `Temporal.PlainMonthDay` instances               | Uses runtime constructor identity when Temporal is available.                                        |\n| `P.literal(value)`                           | one exact value or reference                     | Primitive values match by value; objects, functions, and arrays match by reference identity.         |\n| `P.union(...patterns)`                       | any listed pattern                               | Requires at least one pattern. Commits selections from the successful branch only.                   |\n| `P.exclude(pattern)`                         | values that do not match `pattern`               | Cannot contain `P.select(...)` or `P.collect(...)`.                                                  |\n| `P.optional(pattern)`                        | absent object field, `undefined`, or `pattern`   | Selections inside an absent optional capture `undefined`.                                            |\n| `P.array(pattern)`                           | arrays where every item matches                  | Variable length. Use `P.collect(...)` for repeated captures.                                         |\n| `P.nonEmptyArray(pattern)`                   | non-empty arrays where every item matches        | Same capture rules as `P.array`.                                                                     |\n| `P.map(keyPattern, valuePattern)`            | homogeneous `Map` instances                      | Every Map entry must match the same key and value patterns.                                          |\n| `P.map([keyPattern, valuePattern], ...)`     | required-entry `Map` instances                   | Distinct entries satisfy each clause. Partial by default; `P.exact(...)` rejects extras.             |\n| `P.set(valuePattern)`                        | homogeneous `Set` instances                      | Every Set value must match the pattern.                                                              |\n| `P.set(valuePattern, ...morePatterns)`       | required-value `Set` instances                   | Distinct Set values satisfy each clause. Partial by default; `P.exact(...)` rejects extras.          |\n| `P.tuple([...])`                             | exact tuple pattern                              | Readability helper for bare tuple arrays.                                                            |\n| `P.rest(pattern)`                            | remaining tuple items                            | Valid only as the final tuple item.                                                                  |\n| `P.exact(pattern)`                           | deep exact object/collection pattern             | Rejects object extra keys and required Map/Set extra entries.                                        |\n| `P.when(predicate)`                          | predicate-matched values                         | Supports type guards. Can be nested.                                                                 |\n| `P.instanceOf(Constructor)`                  | `instanceof Constructor`                         | Useful for errors/classes.                                                                           |\n| `P.select()`                                 | anonymous selected value                         | Only one anonymous select is allowed per successful pattern.                                         |\n| `P.select(name)`                             | named selected value                             | Handler receives an object with selected keys.                                                       |\n| `P.select(name, pattern)`                    | named selected value that also matches `pattern` | Combines validation and selection.                                                                   |\n| `P.collect(name, pattern)`                   | repeated values matching `pattern`               | Valid only inside repeated containers. Handler receives `name: T[]`.                                 |\n| `P.record(keyPattern, valuePattern)`         | plain record-like objects                        | Rejects arrays, class instances, maps, sets, dates, regexps, and primitives. Empty records match.    |\n| `P.nonEmptyRecord(keyPattern, valuePattern)` | non-empty plain record-like objects              | Same as `P.record`, but requires at least one enumerable own key.                                    |\n\n### Literal patterns\n\nPlain literals are patterns too:\n\n```ts\nconst label = match(value)\n  .with('ready', () => 'ready')\n  .with(0, () => 'zero')\n  .with(null, () => 'null')\n  .otherwise(() => 'other')\n```\n\nLiteral equality uses `Object.is`, so `NaN`, `-0`, and `0` behave like `Object.is`.\n\nUse `P.literal(value)` when plain pattern syntax would be structural but runtime reference identity matters:\n\n```ts\nconst idKey = { field: 'id' }\nconst value = new Map([[idKey, 'user-123']])\n\nconst id = match(value)\n  .with(P.map([P.literal(idKey), P.string]), (fields) => fields.get(idKey))\n  .otherwise(() => undefined)\n```\n\n### Convenience helpers\n\n`P.regex(regex)` matches strings only. It requires a `RegExp` instance, does not coerce non-string values, starts matching from `lastIndex = 0`, and restores the regex's original `lastIndex` after evaluation.\n\n`P.date` matches valid `Date` instances only. `new Date('bad')` does not match `P.date`; use `P.instanceOf(Date)` when constructor-level matching should include invalid dates.\n\n`P.error` matches `Error` instances including subclasses. `P.regexp` matches regular expression objects, while `P.regex(regex)` matches strings accepted by a regular expression.\n\n`P.nullish` means exactly `null | undefined`. It does not match an absent object property unless the property pattern is wrapped with `P.optional(...)`. `P.falsy` and `P.truthy` follow JavaScript truthiness exactly at runtime.\n\nTemporal helpers are dependency-free and do not polyfill Temporal. When `globalThis.Temporal` is unavailable, `P.temporal` and the specific Temporal helpers match nothing and do not throw. When Temporal constructors are available natively or through a caller-installed global polyfill, helpers use constructor identity such as `value instanceof globalThis.Temporal.PlainDate`; they do not accept duck-typed objects or spoofed `Symbol.toStringTag` values.\n\nThe public Temporal helper types do not require consumers to include TypeScript's `ESNext.Temporal` lib. They use package-local value interfaces so projects can import `@diegogbrisa/ts-match` before Temporal is available in every target TypeScript/runtime combination.\n\n### Object patterns\n\nObject patterns are partial by default:\n\n```ts\nconst name = match(payload)\n  .with({ type: 'user', profile: { name: P.select() } }, (name) => name)\n  .otherwise(() => null)\n```\n\nObject semantics:\n\n- pattern keys use `Reflect.ownKeys(...)`, including symbol keys;\n- value reads use normal JavaScript property access, so getters can run or throw;\n- inherited/prototype properties can match through normal lookup;\n- use `P.exact(...)` to reject enumerable own extra keys.\n\n### Tuple and array patterns\n\nBare arrays are exact tuple patterns. `P.array(...)` is variable-length.\n\n```ts\nconst total = match(values)\n  .with([], () => 0)\n  .with([P.number, P.number], ([left, right]) => left + right)\n  .with(P.tuple([P.number, P.rest(P.number)]), (all) => all.reduce((sum, value) => sum + value, 0))\n  .otherwise(() => -1)\n```\n\nChecked tuple/rest example: [`examples/08-pattern-helpers.ts`](examples/08-pattern-helpers.ts).\n\n### Map and Set patterns\n\n`P.map(...)` and `P.set(...)` match actual `Map` and `Set` instances only. They do not match plain objects, entry arrays, arrays, or duck-typed map-like/set-like objects.\n\nInputs typed as `ReadonlyMap` or `ReadonlySet` are supported by the type layer and keep readonly handler types. Runtime matching still uses actual `Map`/`Set` instances.\n\nHomogeneous mode checks every runtime entry or value:\n\n```ts\nconst scoreTotal = match(\n  new Map([\n    ['a', 1],\n    ['b', 2],\n  ]),\n)\n  .with(P.map(P.string, P.number), (scores) => [...scores.values()].reduce((total, score) => total + score, 0))\n  .otherwise(() => 0)\n\nconst roleCount = match(new Set(['admin', 'owner']))\n  .with(P.set(P.string), (roles) => roles.size)\n  .otherwise(() => 0)\n```\n\nRequired-entry/value mode consumes distinct runtime entries or values. It is partial by default, so extras are allowed:\n\n```ts\nconst metadata = new Map<unknown, unknown>([\n  ['id', 'user-123'],\n  ['count', 2],\n  ['source', 'import'],\n])\n\nconst label = match(metadata)\n  .with(P.map(['id', P.string], ['count', P.number]), () => 'has required metadata')\n  .otherwise(() => 'missing metadata')\n```\n\nWrap required mode in `P.exact(...)` when extras should be rejected:\n\n```ts\nconst exactRoles = match(new Set(['admin', 'owner']))\n  .with(P.exact(P.set('admin', 'owner')), () => true)\n  .otherwise(() => false)\n```\n\nRequired clauses are deterministic: ts-match evaluates clauses left to right, and each clause scans the Map or Set in insertion order for the first unused entry/value that matches. One runtime entry/value cannot satisfy multiple clauses.\n\nTop-level array pairs in `P.map(...)` are entry clauses. Use `P.tuple(...)` when tuple keys or tuple values are intended:\n\n```ts\nconst tupleMap = new Map([[['id', 1] as const, [true, false] as const]])\n\nconst matchedTupleMap = match(tupleMap)\n  .with(P.map(P.tuple([P.string, P.number]), P.tuple([P.boolean, P.boolean])), () => true)\n  .otherwise(() => false)\n```\n\n`P.select(...)` is intentionally rejected inside `P.map(...)` and `P.set(...)`, matching the repeated-container rule used by arrays and records. Use `P.collect(...)` when the handler should receive values gathered from repeated entries or values.\n\nChecked collection example: [`examples/17-collection-helpers.ts`](examples/17-collection-helpers.ts).\n\n### Collection captures\n\n`P.collect(name, pattern)` gathers values from repeated containers into a named handler payload array. It is valid only inside `P.array(...)`, `P.nonEmptyArray(...)`, `P.record(...)`, `P.nonEmptyRecord(...)`, `P.map(...)`, and `P.set(...)`.\n\n```ts\nconst result = match(['u1', 42, 'u2'])\n  .with(P.array(P.union(P.collect('ids', P.string), P.collect('counts', P.number))), ({ ids, counts }) => ({\n    ids,\n    counts,\n  }))\n  .otherwise(() => ({ ids: [], counts: [] }))\n// { ids: ['u1', 'u2'], counts: [42] }\n```\n\n`P.collect(...)` is a matching capture, not a filter. The inner pattern must match. If the list can contain several allowed shapes, make that explicit with `P.union(...)` or another pattern that accepts every allowed item.\n\nEmpty repeated containers that match still provide empty arrays:\n\n```ts\nconst ids = match([])\n  .with(P.array(P.collect('ids', P.string)), ({ ids }) => ids)\n  .otherwise(() => ['fallback'])\n// []\n```\n\nCollection captures can mix with named selections, and duplicate collection names append into the same array. They cannot mix with anonymous `P.select()` and a collection name cannot reuse a named selection name.\n\n```ts\nconst payload = { source: 'sync', users: [{ id: 'u1' }, {}, { id: undefined }] }\n\nconst collected = match(payload)\n  .with(\n    {\n      source: P.select('source', P.string),\n      users: P.array({ id: P.optional(P.collect('ids', P.string)) }),\n    },\n    ({ source, ids }) => ({ source, ids }),\n  )\n  .otherwise(() => ({ source: 'unknown', ids: [] }))\n// { source: 'sync', ids: ['u1', undefined, undefined] }\n```\n\nOrdering follows JavaScript iteration order: array index order, record enumerable key order, Map insertion order, and Set insertion order. Required-entry `P.map(...)` and required-value `P.set(...)` collect only from the entries or values consumed by their clauses; extra entries or values allowed by partial matching are not inspected.\n\n```ts\nconst metadata = new Map<unknown, unknown>([\n  ['id', 'user-123'],\n  ['count', 2],\n  ['source', 'import'],\n])\n\nconst values = match(metadata)\n  .with(P.map(['id', P.collect('values', P.string)], ['count', P.collect('values', P.number)]), ({ values }) => values)\n  .otherwise(() => [])\n// ['user-123', 2]\n```\n\n## Named `p*` helper exports\n\nEvery `P` helper is also exported as a named helper. Named imports are useful when codebases prefer focused imports or bundlers can tree-shake individual symbols more visibly.\n\nChecked example using named helper imports: [`examples/09-named-helper-imports.ts`](examples/09-named-helper-imports.ts).\n\n| Named export                                | Equivalent                                   |\n| ------------------------------------------- | -------------------------------------------- |\n| `pWildcard`                                 | `P._`                                        |\n| `pAny`                                      | `P.any`                                      |\n| `pString`                                   | `P.string`                                   |\n| `pNumber`                                   | `P.number`                                   |\n| `pBoolean`                                  | `P.boolean`                                  |\n| `pBigint`                                   | `P.bigint`                                   |\n| `pSymbol`                                   | `P.symbol`                                   |\n| `pNull`                                     | `P.null`                                     |\n| `pUndefined`                                | `P.undefined`                                |\n| `pNan`                                      | `P.nan`                                      |\n| `pFinite`                                   | `P.finite`                                   |\n| `pInteger`                                  | `P.integer`                                  |\n| `pRegex(regex)`                             | `P.regex(regex)`                             |\n| `pDate`                                     | `P.date`                                     |\n| `pError`                                    | `P.error`                                    |\n| `pRegexp`                                   | `P.regexp`                                   |\n| `pNullish`                                  | `P.nullish`                                  |\n| `pFalsy`                                    | `P.falsy`                                    |\n| `pTruthy`                                   | `P.truthy`                                   |\n| `pTemporal`                                 | `P.temporal`                                 |\n| `pTemporalInstant`                          | `P.temporalInstant`                          |\n| `pTemporalPlainDate`                        | `P.temporalPlainDate`                        |\n| `pTemporalPlainTime`                        | `P.temporalPlainTime`                        |\n| `pTemporalPlainDateTime`                    | `P.temporalPlainDateTime`                    |\n| `pTemporalZonedDateTime`                    | `P.temporalZonedDateTime`                    |\n| `pTemporalDuration`                         | `P.temporalDuration`                         |\n| `pTemporalPlainYearMonth`                   | `P.temporalPlainYearMonth`                   |\n| `pTemporalPlainMonthDay`                    | `P.temporalPlainMonthDay`                    |\n| `pLiteral(value)`                           | `P.literal(value)`                           |\n| `pUnion(...)`                               | `P.union(...)`                               |\n| `pExclude(pattern)`                         | `P.exclude(pattern)`                         |\n| `pOptional(pattern)`                        | `P.optional(pattern)`                        |\n| `pArray(pattern)`                           | `P.array(pattern)`                           |\n| `pNonEmptyArray(pattern)`                   | `P.nonEmptyArray(pattern)`                   |\n| `pMap(...)`                                 | `P.map(...)`                                 |\n| `pSet(...)`                                 | `P.set(...)`                                 |\n| `pTuple([...])`                             | `P.tuple([...])`                             |\n| `pRest(pattern)`                            | `P.rest(pattern)`                            |\n| `pExact(pattern)`                           | `P.exact(pattern)`                           |\n| `pWhen(predicate)`                          | `P.when(predicate)`                          |\n| `pInstanceOf(Constructor)`                  | `P.instanceOf(Constructor)`                  |\n| `pSelect(...)`                              | `P.select(...)`                              |\n| `pCollect(name, pattern)`                   | `P.collect(name, pattern)`                   |\n| `pRecord(keyPattern, valuePattern)`         | `P.record(keyPattern, valuePattern)`         |\n| `pNonEmptyRecord(keyPattern, valuePattern)` | `P.nonEmptyRecord(keyPattern, valuePattern)` |\n\n## `isMatching`\n\n`isMatching` checks a pattern and returns a type guard.\n\nTwo call forms are supported:\n\n```ts\nisMatching(pattern, value)\nisMatching(pattern)(value)\n```\n\nTypical usage:\n\n```ts\nconst isUser = isMatching({ type: 'user', id: P.string })\nconst users = values.filter(isUser)\n```\n\nChecked example: [`examples/10-is-matching.ts`](examples/10-is-matching.ts).\n\nUse `isMatching` when a branch should continue only if a value matches. Use `assertMatching` when a mismatch should throw.\n\n## `assertMatching`\n\n`assertMatching(pattern, value)` throws `PatternMismatchError` when the value does not match. After a successful call, TypeScript narrows the value.\n\n```ts\nconst form = Object.fromEntries(new URLSearchParams('type=user&id=u1&role=admin'))\n\nassertMatching({ type: 'user', id: P.string, role: P.union('admin', 'member') }, form)\n\nform.id // string\n```\n\nChecked example: [`examples/11-assert-matching.ts`](examples/11-assert-matching.ts).\n\nUse it at runtime boundaries: request bodies, form data, API payloads, webhook events, storage reads, and test fixtures.\n\n## Error classes\n\n### `NonExhaustiveMatchError`\n\nThrown by `.exhaustive()` and exhaustive `matchBy(...).cases(...)` paths when runtime data reaches an unhandled branch. In TypeScript code this is usually prevented by the type system, but it can still happen with JavaScript callers or incorrectly typed runtime data.\n\nProperties:\n\n- `name: 'NonExhaustiveMatchError'`\n- `message`\n- `valuePreview: string`\n- `matcher: 'match' | 'matchBy' | 'isMatching' | 'assertMatching' | undefined`\n- `key: PropertyKey | undefined`\n- `path: string | undefined`\n- `tag: unknown`\n- non-enumerable `value: unknown`\n\n### `PatternMismatchError`\n\nThrown by `assertMatching(pattern, value)`.\n\nProperties:\n\n- `name: 'PatternMismatchError'`\n- `message`\n- `valuePreview: string`\n- `patternPreview: string`\n- non-enumerable `value: unknown`\n- non-enumerable `pattern: unknown`\n\nBoth public error classes preserve `instanceof` identity when ESM imports and CommonJS `require(...)` load the package in the same process.\n\nChecked example: [`examples/12-error-handling.ts`](examples/12-error-handling.ts).\n\nThe ts-match errors subpath (`@diegogbrisa/ts-match/errors`) also currently exports `preview(value)` and the `MatchErrorMetadata` interface used by `NonExhaustiveMatchError`. They are low-level diagnostic exports; normal application code should prefer the error classes.\n\n## TypeScript inference guide\n\n### Handler parameters are narrowed\n\n```ts\nconst text = matchBy(action, 'type')\n  .with('load-success', (action) => action.rows.join(','))\n  .with('load-failure', (action) => action.message)\n  .with('clear', () => '')\n  .with('start-loading', () => '')\n  .exhaustive()\n```\n\nEach handler sees only the variant for its tag.\n\n### Return types are inferred\n\n`match(...)`, `matchBy(...)`, and their promise forms infer the union of branch return values. Promise terminals wrap the awaited return in a promise.\n\n### Selections change the handler payload\n\nWithout selections, handlers receive the matched value. With one anonymous selection, handlers receive that selected value. With named selections, handlers receive an object of selected values.\n\n```ts\nconst selected = match(payload)\n  .with(\n    { profile: { name: P.select('name', P.string), age: P.select('age', P.number) } },\n    ({ name, age }) => `${name}:${age}`,\n  )\n  .otherwise(() => null)\n```\n\n### Collection captures gather repeated values\n\nInside repeated containers, `P.collect(name, pattern)` contributes a named array to the handler payload. The element type comes from the inner pattern, and duplicate collection names union their element types.\n\n```ts\nconst summary = match(items)\n  .with(P.array(P.union(P.collect('values', P.string), P.collect('values', P.number))), ({ values }) => values)\n  .otherwise(() => [])\n// values: (string | number)[]\n```\n\n### Exhaustiveness catches missing cases\n\nFor closed unions, `.exhaustive()` is available only after all remaining variants are covered. `matchBy(...).cases({...})` requires a complete object map when object keys can represent every discriminant.\n\n## TypeScript diagnostics and troubleshooting\n\n`ts-match` cannot replace TypeScript's compiler diagnostics, but invalid usage is shaped to surface readable `ts-match:` messages in IDE errors. Read the `ts-match:` line first; it names the library concept, the violated rule, and usually the fix.\n\nThe checked diagnostic fixtures live in [`diagnostics/`](diagnostics/) and are verified by `pnpm test:diagnostics`.\n\n### Missing exhaustive cases\n\n```ts\nmatchBy(event, 'type')\n  .with('open', (event) => event.payload.id)\n  .exhaustive()\n```\n\nProduces a diagnostic containing:\n\n```text\nts-match: matchBy is not exhaustive for the selected path. Add handlers for the remaining tag(s), or use .otherwise(...) when a fallback is intentional.\n```\n\nFix by adding the missing `.with(...)` branches, or use `.otherwise(...)` when a fallback is part of the design.\n\n### Invalid paths\n\n```ts\nmatchBy(event, 'payload.missing')\nmatchBy(event, ['payload', 'missing'])\n```\n\nProduces:\n\n```text\nts-match: invalid matchBy path. Use an existing direct key, valid dot path, or tuple path. Use tuple paths for symbol keys or keys that contain dots.\n```\n\nFix the path. Use dot paths for normal nested string keys and tuple paths for symbols or literal keys containing `.`.\n\n### Impossible cases\n\n```ts\nmatch(action).with({ type: 'missing' }, () => 'bad')\nmatchBy(action, 'type').with('missing', () => 'bad')\n```\n\nProduce diagnostics containing:\n\n```text\nts-match: this pattern cannot match the current input type.\nts-match: this matchBy tag cannot occur at the selected path.\n```\n\nFix the literal/tag, remove the unreachable branch, or narrow/widen the input type before matching.\n\n### Invalid pattern helper placement\n\n```ts\nP.array(P.select('item'))\nP.collect('item', P.string)\nP.exclude(P.select('x'))\nP.exclude(P.collect('x', P.string))\nP.tuple([P.rest(P.string), P.number])\n```\n\nProduce diagnostics containing:\n\n```text\nts-match: repeated container patterns cannot contain P.select(...).\nts-match: invalid P.collect(...) usage.\nts-match: P.exclude(pattern) cannot contain P.select(...).\nts-match: P.exclude(pattern) cannot contain P.collect(...).\nts-match: invalid P.rest(...) usage.\n```\n\nMove selections outside repeated or negative contexts. Use `P.collect(name, pattern)` inside repeated containers when you need many captures. `P.rest(...)` belongs only as the final tuple item.\n\n### Object-map case mistakes\n\n```ts\nmatchBy(event, 'type').cases({ open: (event) => event.payload.id })\n```\n\nProduces:\n\n```text\nts-match: object-map cases are missing required key(s). Add handlers for the missing keys or use .partial(...).otherwise(...).\n```\n\nExtra keys, broad tags, `null`/`undefined`, and normalized key collisions also produce `ts-match:` diagnostics. Use tuple-entry cases or callback grouped cases when object keys cannot represent the tags:\n\n```ts\nconst label = matchBy(state, 'kind').cases((group) => [\n  group('ready', (state) => state.data),\n  group(null, () => 'empty'),\n])\n```\n\n### Grouped-case inference\n\nPrefer callback grouped cases when handlers need inferred variants:\n\n```ts\nmatchBy(event, 'type').cases((group) => [group('open', 'close', (event) => event.type), group('idle', () => 'idle')])\n```\n\nArray-form callback groups are still supported without `as const` and can be more readable when their tags are statically known, but use the variadic form above when you want tag suggestions while typing:\n\n```ts\nmatchBy(event, 'type').cases((group) => [group(['open', 'close'], (event) => event.type), group('idle', () => 'idle')])\n```\n\nInline tuple-entry arrays preserve handler narrowing without const assertions. Partial grouped arrays preserve tag autocomplete while editing grouped tags; exhaustive `.cases([...])` keeps missing-case diagnostics active while the list is incomplete, so variadic callback `group('a', 'b', handler)` is the autocomplete-friendly exhaustive grouped form. Dynamic runtime arrays are accepted at runtime but cannot prove that every tag is covered.\n\nStandalone exported `group(...)` is useful for reusable groups, but because it is created before `.cases(...)` or `.partial(...)` has context, handler annotations can still help in complex prebuilt tuple/group arrays. Do not add unsafe casts; use callback `group` first.\n\n### Boundary assertions\n\n`isMatching(...)` and `assertMatching(...)` validate pattern structure too. If an assertion pattern contains invalid selection/rest placement, the diagnostic appears before runtime:\n\n```text\nts-match: invalid P.select(...) usage.\nts-match: invalid P.rest(...) usage.\n```\n\n### Readonly tuples and objects\n\nReadonly tuple and object inputs are supported by the type tests and examples. Inline matcher arrays preserve literal tags without const assertions.\n\n## Performance guide\n\nPerformance guidance is intentionally practical, not absolute:\n\n- The package has zero runtime dependencies and `sideEffects: false`.\n- Prefer `matchBy(value, 'type')` for straightforward discriminated-union dispatch when one key determines the branch.\n- Use `.with(...).exhaustive()` as the default guide/example shape for closed discriminated unions: it keeps strong inference, avoids inline object-map allocation, and reads in execution order.\n- Use inline `.cases({...})` for compact map-style DX in ordinary non-hot code.\n- Avoid inline `.cases({...})` in hot loops because it recreates maps/handlers and validates fresh objects.\n- Hoisted `matchBy(...).cases(caseMap)` is currently the fastest measured `ts-match` discriminant-dispatch shape in `benchmarks/native.ts`. In local runs it is roughly 15x faster than inline `.cases({...})` and about 4x faster than chained `.with(...).exhaustive()` dispatch for simple discriminants. Treat those ratios as directional, not guaranteed; benchmark on your workload. Hoisting is a deliberate performance/DX tradeoff because reusable handler maps can lose contextual inference. Do not use it as the default user-facing style.\n- Hoist reusable patterns and validators when that preserves inference, for example `const isTelemetry = isMatching(P.exact(...))`.\n- Measure locally with `pnpm bench:native`. The benchmark includes inline object maps, hoisted object maps, grouped callback cases, structural patterns, predicate patterns, `isMatching`, and promise terminals.\n\nChecked performance-style example: [`examples/14-performance-friendly-hoisting.ts`](examples/14-performance-friendly-hoisting.ts).\n\nBenchmark file included with the package:\n\n- [`benchmarks/native.ts`](benchmarks/native.ts)\n\nThe repository also contains the development-only `benchmarks/dispatch.ts` strategy benchmark, runnable with `pnpm bench:dispatch`.\n\n## Limitations and tradeoffs\n\n- **ESM first.** ESM imports are the primary package path; CommonJS `require(...)` and no-`type` `tsx` scripts use a compatibility build from the package export map.\n- **Node 20+.** Older runtimes are not targeted.\n- **Temporal availability is runtime-owned.** Temporal helpers do not polyfill `globalThis.Temporal`; they match nothing until the runtime or application provides Temporal constructors.\n- **Selections are intentionally restricted in repeated contexts.** `P.array(...)`, `P.nonEmptyArray(...)`, `P.record(...)`, `P.nonEmptyRecord(...)`, `P.map(...)`, and `P.set(...)` reject `P.select(...)` because captures may repeat ambiguously. Use `P.collect(...)` for repeated captures.\n- **`P.collect(...)` is not a filter.** The inner pattern must match; use `P.union(...)` when a repeated container can hold multiple allowed shapes.\n- **`P.exclude(...)` cannot contain captures.** Excluding a pattern should not capture data from a branch that did not match.\n- **`P.rest(...)` is tuple-only and must be final.** Runtime misuse throws `TypeError`.\n- **Object patterns use normal JavaScript property lookup.** Getters can run or throw, and inherited properties can match.\n- **`P.exact(...)` checks extras on values.** It is deep for object patterns and rejects extra required Map/Set entries, but it is not a cyclic-graph matcher.\n- **Dot ","readmeFilename":"README.md"}