Are Named Capture Groups in Typescript Regex malfunctioning?

Update: I have included @babel/plugin-transform-named-capturing-groups-regex, following the suggestion from @Jack Misteli to explore Babel.

Update:: Utilizing https://babeljs.io/en/repl#?browsers=defaults%2C%20not%20ie%2011%2C%20not%20ie_mob%2011&build=&builtIns=false&spec=false&loose=false&code_lz=PQKhCgAIOyAEAOBDATkgtpA3gZwC4oCWAdg...oment Natively


I am attempting to comprehend what is causing this regular expression to break in Typescript (whether it's my configuration, the language itself, etc.).

Specifically, it seems to be related to the named capture groups I was using because removing them makes the code functional.

Original TS file:

/**
 *
 * @param {string} markdownLink A link in the form of [title](link description)
 * @returns {object} An object with three keys: title, link, description
 */
export function parseLink(markdownLink: string) {
    const pattern: RegExp = new RegExp(
        /^(\[(?<title>[^\]]*)?\]\((?<link>[A-Za-z0-9\:\/\.\- ]+)(?<description>\"(.+)\")?\))/
    )

    const match = markdownLink.match(pattern)
    const groups = match?.groups
    return groups
}
...

My .babelrc:

{
    "presets": ["@babel/preset-env", "@babel/preset-typescript"],
    "plugins": [
        "@babel/plugin-proposal-class-properties",
        "@babel/plugin-transform-runtime",
        "@babel/plugin-transform-named-capturing-groups-regex"
    ]
}

...

If I remove the named capture groups, it does seem to work, though I'm now struggling to understand why I have a duplicate full capture group.

https://i.sstatic.net/UHuqt.png

...

The debugger on the left shows the value of parsed, which is the variable assigned to the return of the transpiled version.

So, here are my questions:

  1. Is there something I need to do to enable named capture groups in TS?
  2. Is there an explanation for why I'm receiving a duplicate group in the transpiled version?
  3. Is there a more efficient approach to handling this situation?
  4. What am I missing in configuring the named capture groups plugin that is preventing it from returning a match when present?

Answer №1

The issue at hand is not related to Typescript but rather to Babel. It seems that named regular expressions, a feature introduced in ES2018, are causing the problem. In order to utilize this feature, proper configuration of Babel is necessary. Based on my understanding, it appears that the regex pattern is transformed during transpilation to fit Babel's _wrapRegExp structure (which I am unsure about the internal workings). Consequently, simply copying and pasting the pattern into tools like https://regex101.com may not yield the expected results due to differences in Regex engines.

It seems that there is inconsistency in the code samples you provided, particularly in how the regex is constructed and the absence of console logs. Additionally, the discrepancy between the logs displayed in your screenshot and the actual code is evident.

None of the code snippets seem to accurately match the groups. To facilitate a thorough comparison, I have created a CSB snippet that only returns the match array. The result indicates that everything aligns with each other: https://codesandbox.io/s/wizardly-bird-jm74k?file=/src/index.js. I also crafted a JS rendition of your Typescript code and a babelized version of the file for review, both yielding consistent match results.

Upon testing with the provided test string, all outcomes remain identical across the board. This suggests that the functionality is operating as intended!

[test](http://google.com "hello")
[test](https://google.com "hello")
[test](google.com)
[](google.com)
[test](google.com "hello")

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Stop MatDialog instance from destroying

In my application, I have a button that triggers the opening of a component in MatDialog. This component makes API calls and is destroyed when the MatDialog is closed. However, each time I open the MatDialog for the second time by clicking the button agai ...

What is the best approach to retrieve all user information using React with TypeScript and the Redux Toolkit?

I'm currently using React with TypeScript and Redux Toolkit, but I've hit a roadblock trying to retrieve user information. Below is my userSlice.ts file: export const userSlice = createSlice({ name: "user", initialState: { user: null, } ...

Is searching for duplicate entries in an array using a specific key?

Below is an array structure: [ { "Date": "2020-07", "data": [ { "id": "35ebd073-600c-4be4-a750-41c4be5ed24a", "Date": "2020-07-03T00:00:00.000Z", ...

Is there a way to retrieve the Route object in Angular based on a url string?

Is there a way to extract Route object by passing a URL? interface Route { path?: string; pathMatch?: string; matcher?: UrlMatcher; component?: Type<any>; redirectTo?: string; outlet?: string; canActivate?: any[]; can ...

What is the best method to publish my npm package so that it can be easily accessed through JSDelivr by users?

I've been working on creating an NPM package in TypeScript for educational purposes. I have set up my parcel configuration to export both an ESM build and a CJS build. After publishing it on npm, I have successfully installed and used it in both ESM-m ...

I am interested in understanding the significance of importing `Footer` before `components/Menu` in terms of import order

What is the reason behind this happening? ./pages/index.tsx 3:1 Error: The import of components/Footer/Footer should come before the import of components/Menu. This relates to import order. ...

Updating the text area value based on the selected option in a dropdown using Typescript within Angular6

I'm currently facing an issue with updating the text area value based on the selection from a dropdown menu. Below is the design of the dialog: https://i.sstatic.net/67U1M.png Here's the code snippet I've incorporated for this functionalit ...

Component throwing error when receiving an array in React (TypeScript)

Encountering an issue when trying to specify inputs for Component 2. Seeking guidance on how to properly pass and describe arrays input. Data Model: interface IIncident { id: string, title: string } Component 1: interface IncidentManagerProps { ...

The functionality of the System JS map is not functioning properly

Despite the challenges I face with System.js, I find it to be a valuable tool that I prefer over alternatives. This is my current System.js configuration: System.config({ packages: { app: { format: 'register' ...

How can I prompt TypeScript to flag null comparisons with a non-nullable field?

Is there a way to have TypeScript detect this issue? My strictNullChecks setting is enabled. const foo: string = 'asdf'; if (foo !== null) { console.log(foo); } If I modify that condition to: if (foo !== 42) { The error message displayed ...

The material-ui.dropzone component requires a suitable loader to efficiently manage this specific type of file

I encountered an error while trying to integrate material-ui-dropzone into my React app: ./~/material-ui-dropzone/src/index.jsx Module parse failed: ...\client\node_modules\material-ui-dropzone\src\index.jsx Unexpected token ...

Setting a TypeScript collection field within an object prior to sending an HTTP POST request

Encountered an issue while attempting to POST an Object (User). The error message appeared when structuring it as follows: Below is the model class used: export class User { userRoles: Set<UserRole>; id: number; } In my TypeScript file, I included ...

What is a mapped Record type in which each key K in Record<T, K> is determined by the value of T?

My previous question from three weeks ago has led to this extension: Set the keys of an interface to the possible values of a different interface? In summary, I have the following type definitions: interface SuccessStatus { type: 'success'; ...

Customize drawerLabel in React Native based on user's current location

I am facing an issue with my react-native application where I need to dynamically render a menu item based on the user's location. However, since the function that fetches the user location is asynchronous, I am encountering an undefined error. My que ...

Angular - Automatically hide sidebar menu upon selecting a menu item

Struggling to hide a sidebar menu after clicking on a menu item that you created? I ran into the same issue and tried following the example from a tutorial on Do I really need to call toggleMenu on (click) of every hyperlink in the HTML? If so, how do I i ...

Unit Testing in Vue.JS: The original function remains active even after using sinon.stub()

While unit testing my components (which are coded using TypeScript along with vue-class-component), I am utilizing Sinon to stub API calls. However, even after adding the stub to the test, the original method is still being invoked instead of returning the ...

How Typescript Omit/Pick erases Symbols in a unique way

Recently, I have delved into TypeScript and started working on developing some custom utilities for my personal projects. However, I encountered an issue with type mapping involving Pick/Omit/Exclude and other typing operations where fields with symbol key ...

Material Angular table fails to sort columns with object values

Currently, I am in the process of developing a web application using Angular Material. One of the challenges I have encountered is displaying a table with sorting functionality. While sorting works perfectly fine on all columns except one specific column. ...

Typedoc does not create documentation for modules that are imported

Whenever I generate documentation with TypeDoc, I am encountering an issue where imported files come up empty. If I add a class to the file specified in entryPoints, I get documentation for that specific class. However, the imported files show no document ...

How can one specify a type in Typescript with a precise number of properties with unspecified names?

Imagine I have a variable with a name and a value, both of which I need for a specific task such as logging. This can be achieved in the following way: const some_variable = "abcdef" const another_variable = 12345 const log1 = (name: string, value: any) ...