+1
-1
@@ -295,3 +295,3 @@ import type { contains, ErrorMessage, noSuggest, NumberLiteral, setIndex, unionKeyOf, writeUnclosedGroupMessage, writeUnmatchedGroupCloseMessage, ZeroWidthSpace } from "@ark/util"; | ||
| export declare namespace QuantifierTree { | ||
| type finalize<self extends QuantifierTree, ctx extends FinalizationContext> = finalizeTree<self["ast"], ctx> extends infer r ? r extends FinalizationResult ? finalizeQuantifierResult<self, ctx, r> : never : never; | ||
| type finalize<self extends QuantifierTree, ctx extends FinalizationContext> = finalizeTree<self["ast"], ctx> extends infer r extends FinalizationResult ? finalizeQuantifierResult<self, ctx, r> : never; | ||
| type finalizeQuantifierResult<self extends QuantifierTree, ctx extends FinalizationContext, r extends FinalizationResult, quantifiedCaptures extends IndexedCaptures = extractNewCaptures<ctx["captures"], r["ctx"]["captures"]>> = self["min"] extends 0 ? quantifiedCaptures extends [] ? finalizeNonZeroMinQuantified<self, r> : finalizeZeroMinQuantifiedWithCaptures<self, ctx, r, quantifiedCaptures> : finalizeNonZeroMinQuantified<self, r>; | ||
@@ -298,0 +298,0 @@ type finalizeNonZeroMinQuantified<self extends QuantifierTree, r extends FinalizationResult> = FinalizationResult.from<{ |
+10
-5
| { | ||
| "name": "@ark/regex", | ||
| "version": "0.0.0", | ||
| "description": "A drop-in replacement for new RegExp() with types", | ||
| "version": "0.0.1", | ||
| "license": "MIT", | ||
@@ -18,5 +19,9 @@ "author": { | ||
| }, | ||
| "./internal/*": { | ||
| "ark-ts": "./*", | ||
| "default": "./out/*" | ||
| "./internal/*.ts": { | ||
| "ark-ts": "./*.ts", | ||
| "default": "./out/*.js" | ||
| }, | ||
| "./internal/*.js": { | ||
| "ark-ts": "./*.ts", | ||
| "default": "./out/*.js" | ||
| } | ||
@@ -28,3 +33,3 @@ }, | ||
| "dependencies": { | ||
| "@ark/util": "0.50.0" | ||
| "@ark/util": "0.52.0" | ||
| }, | ||
@@ -31,0 +36,0 @@ "publishConfig": { |
+30
-42
@@ -1,71 +0,59 @@ | ||
| # @ark/regex | ||
| # arkregex | ||
| A drop-in replacement for `new RegExp()` with types. | ||
| A drop-in replacement for `new RegExp()` with types | ||
| ## Usage | ||
| The `regex` function creates a `Regex` instance with types for `.test()`, `.exec()` and more, statically parsed from native JS syntax. | ||
| The `regex` function creates a `Regex` instance with types for `.test()`, `.exec()` and more, statically parsed from native JS syntax: | ||
| ```ts | ||
| import { regex } from "@ark/regex" | ||
| import { regex } from "arkregex" | ||
| const ok = regex("^ok$", "i") | ||
| // Regex<"ok" | "oK" | "Ok" | "OK", { flags: "i" }> | ||
| const semver = regex("^(\\d*)\\.(\\d*)\\.(\\d*)$") | ||
| // Type: Regex<`${bigint}.${bigint}.${bigint}`, { captures: [`${bigint}`, `${bigint}`, `${bigint}`] }> | ||
| // Regex<`${bigint}.${bigint}.${bigint}`, { captures: [`${bigint}`, `${bigint}`, `${bigint}`] }> | ||
| const email = regex("^(?<name>\\w+)@(?<domain>\\w+\\.\\w+)$") | ||
| // Type: Regex<`${string}@${string}.${string}`, { names: { name: string; domain: `${string}.${string}`; }; ...> | ||
| // Regex<`${string}@${string}.${string}`, { names: { name: string; domain: `${string}.${string}`; }; ...> | ||
| ``` | ||
| ## Features | ||
| All you need to get started is `pnpm install arkregex` (or the equivalent for your package manager of choice) 🎉 | ||
| ### Features | ||
| - **Types**: Infers string types for your existing regular expressions, including positional and named captures | ||
| - **Parity**: Supports 100% of [features](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions) allowed by `new RegExp()` | ||
| - **Safety**: Syntax errors like referencing a group that doesn't exist are now type errors | ||
| - **Zero Runtime**: Improves your type safety without impacting your bundle size[\*](#footnote) | ||
| - **Zero Runtime**: Improves your type safety without impacting your bundle size | ||
| ## Examples | ||
| ### FAQ | ||
| ```ts | ||
| // Anchored patterns | ||
| const start = regex("^hello") // Type: Regex<`hello${string}`, {}> | ||
| const end = regex("world$") // Type: Regex<`${string}world`, {}> | ||
| const exact = regex("^hello$") // Type: Regex<"hello", {}> | ||
| #### Why aren't some patterns like `[a-Z]` inferred more precisely? | ||
| // Quantifiers | ||
| const optional = regex("^colou?r$") // Type: Regex<"color" | "colour", {}> | ||
| const multiple = regex("^a+$") // Type: Regex<`a${string}`, {}> | ||
| Constructing string literal types for these sorts of expressions is combinatorial and will explode very quickly if we infer character ranges like this as literal characters. | ||
| // Character classes | ||
| const digits = regex("^\\d+$") // Type: Regex<`${bigint}`, {}> | ||
| const words = regex("^\\w+$") // Type: Regex<string, {}> | ||
| We've tried to strike a balance between performance and precision while guaranteeing that the inferred types are at worst imprecise and never incorrect. | ||
| // Capture groups | ||
| const captured = regex("^(\\w+):(\\d+)$") | ||
| // Type: Regex<`${string}:${bigint}`, { captures: [string, `${bigint}`] }> | ||
| #### Why doesn't it work with my massive RegExp? | ||
| // Case-insensitive flag | ||
| const caseInsensitive = regex("^ok$", "i") | ||
| // Type: Regex<"ok" | "oK" | "Ok" | "OK", { flags: "i" }> | ||
| ``` | ||
| ## FAQ | ||
| ### Why doesn't it work with my massive RegExp? | ||
| If your expression is especially long or complex, TypeScript won't be able to infer it. | ||
| If your types start to slow down or you see the dreaded `Type is excessively deep...`, you can manually type your expression: | ||
| If your types start to slow down or you see the dreaded `Type is excessively deep...`, you can manually type your expression using `regex.cast`: | ||
| ```ts | ||
| // For complex patterns, use the typed Regex class directly | ||
| const complexPattern: Regex<"complex-string", { captures: [string, string] }> = | ||
| new RegExp("very-long-complex-pattern-here") as never | ||
| const complexPattern = regex.cast<`pattern-${string}`, { captures: [string] }>( | ||
| "very-long-complex-expression-here" | ||
| ) | ||
| ``` | ||
| <a id="footnote"></a> | ||
| \*The actual runtime bundle size is two lines: | ||
| #### Is it robust? | ||
| ```ts | ||
| export const regex = (src, flags) => new RegExp(src, flags) | ||
| Object.assign(regex, { cast: regex }) | ||
| ``` | ||
| `arkregex` types are [extensively tested](https://github.com/arktypeio/arktype/tree/main/ark/regex/__tests__/regex.test.ts) and [benchmarked](https://github.com/arktypeio/arktype/tree/main/ark/regex/__tests__/regex.bench.ts) using [attest](https://github.com/arktypeio/arktype/tree/main/ark/attest#readme). | ||
| If anything not covered by the other FAQs is not behaving how you'd expect, please don't hesitate to [create an issue](https://github.com/arktypeio/arktype/issues/new). | ||
| #### How can I get syntax highlighting for `regex`? | ||
| The [ArkType extension](https://marketplace.visualstudio.com/items?itemName=arktypeio.arkdark) can be installed to add syntax highlighting to `regex` calls. |
47477
0.85%60
-16.67%+ Added
- Removed
Updated