Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@std/regexp: convert weakly typed replace/replaceAll positional args to strongly typed params object #6324

Open
lionel-rowe opened this issue Jan 1, 2025 · 0 comments

Comments

@lionel-rowe
Copy link
Contributor

Is your feature request related to a problem? Please describe.

Due to the design of the String#replace/String#replaceAll callback function, its arguments can only be typed [substring: string, ...args: any[]] in TypeScript. This is because there are zero-to-many arguments starting at index 1 that are the results of each capture group (including named capture groups). To get a specific argument, counting from the start is a bad solution because each capture group added increases the number of arguments; meanwhile, counting backward from the end is also a bad solution because if you refactor numbered groups to named groups or vice-versa, the total number of arguments changes. All of this makes such callbacks really annoying to work with if you want to grab the later arguments, such as the match index or groups. The only reliable solution is to runtime check the type of an argument after the positional ones (I usually check for number and then count forward/backward from there).

Describe the solution you'd like

A function parseReplaceArgs that takes the weakly typed positional arguments of a String#replace/String#replaceAll callback, either as an array or as spread arguments, and returns a strongly typed object with helpfully named props. Usage something like this:

str.replace(re, (...args) => {
    // fullMatch: string
    // index: number
    // namedGroups: Partial<Record<string, string>> | undefined
    // numberedGroups: Partial<Record<number, string>>
    // input: string
    const { fullMatch, index, namedGroups, numberedGroups, input } = parseReplaceArgs(args)
})

Describe alternatives you've considered

A higher-order function createReplaceFunction that takes a callback with a params object and passes the positional args as props to that object:

str.replace(re, createReplaceFunction(({ fullMatch, index, namedGroups, numberedGroups, input }) => {
    // fullMatch: string
    // index: number
    // namedGroups: Partial<Record<string, string>> | undefined
    // numberedGroups: Partial<Record<number, string>>
    // input: string
}))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant