npm version bundle size npm monthly downloads typescript license: MIT github stars
A strictly typed & minimal RegExp wrapper.
const groups1 = new RegExp('^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})$', 'g').exec('9999-12-31')!.groups; // ⤴ '{ [key: string]: string; } | undefined' 🤮 const groups2 = typedRegExp('^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})$', 'g').exec('9999-12-31')!.groups; // ⤴ '{ year: string, month: string, day: string }' 🥰
▶ Try it in the TypeScript Playground
- Install
ts-regexp
# Using npm npm install ts-regexp # Using yarn yarn add ts-regexp # Using pnpm pnpm add ts-regexp
- Import
typedRegExp
:
import { typedRegExp } from 'ts-regexp';
Import and use typedRegExp
just like the native RegExp
constructor:
import { typedRegExp } from 'ts-regexp'; const datePattern = typedRegExp('(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})'); const emailPattern = typedRegExp('^(?<local>[a-z0-9._%+-]+)@(?<domain>[a-z0-9.-]+\.[a-z]{2,})$', 'i');
The function signature is:
typedRegExp(pattern: string, flags?: string)
Note:
typedRegExp
returns a plain object, not aRegExp
instance.
All standard RegExp
methods work exactly as expected, but with equivalent or improved typing:
const pattern = typedRegExp('(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})', 'gid'); // Standard methods pattern.exec('1970-01-01')!.groups; // { year: string; month: string; day: string; } pattern.test('1970-01-01'); // boolean // Access RegExp properties pattern.source; // "(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})" pattern.flags; // "dgi" pattern.global; // true pattern.sticky; // false // ...
Each RegExp
-related string.prototype
method is available as ${MethodName}In
with equivalent or improved typing:
const pattern = typedRegExp('(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})'); const string = '1976-11-21'; // Instead of: string.match(pattern) const match = pattern.matchIn(string); // typed match // Instead of: string.replace(pattern, replacement) const formatted1 = pattern.replaceIn(string, '$<day>/$<month>/$<year>'); const formatted2 = pattern.replaceIn(string, (match, year, month, day, offset, string, groups) => `${groups.day}/${groups.month}/${groups.year}`); // typed arguments // Other inversed methods pattern.searchIn(string); // like string.search(pattern) pattern.splitIn(string); // like string.split(pattern)
When using the global (g
) flag, additional methods become available:
const pattern = typedRegExp('\\d', 'g'); // Only available with 'g' flag pattern.matchAllIn('1973-12-08'); // like string.matchAll(pattern) pattern.replaceAllIn('123-456', '#'); // like string.replaceAll(pattern, replacement)
If you need access to the underlying RegExp
instance:
const pattern = typedRegExp('\\d+'); const nativeRegExp = pattern.regExp; // Regular RegExp instance
- ✅ Strictly typed named & unnamed capture groups
- ✅ Supports contextual awareness
- ✅ Parses:
- nested groups
- different group types (non-capturing, lookarounds, named captures, etc.)
- alternation
- character classes and escaped characters
- ✅ Infers group optionality from quantifiers (
?
,*
,{n,m}
) - ✅ Validates flags
- ✅ Supports dynamic (non-literal) pattern + flag inputs
📋 Planned