Assistance with Optimizing TypeScript - "The depth of type instantiation is overly excessive, potentially leading to an infinite loop. (Error code:

I'm currently working on extracting data- attributes from a complete object of element attributes using TypeScript code. However, I've encountered an error message stating "Type instantiation is excessively deep and possibly infinite (2589)."

It seems that my code might need optimization to resolve this issue—I suspect that it could be overly complex—so I would greatly appreciate guidance from an expert to determine if there's a solution or if the task I'm attempting is too challenging.

You can find the TypeScript Repl here, and I've shared the code below:

type AnyArray = any[];
type AnyArrayWithItems = [any, ...any];
type AnyFunction<Arguments extends any[] = any[]> = (...args: Arguments) => any;

// Define the type of the first item in an array.
type Head<SomeArray extends AnyArray> = SomeArray extends AnyArrayWithItems
    ? SomeArray[0]
    : never;

// Define the type of an array after removing the first element.
type Tail<SomeArray extends AnyArray> = AnyFunction<SomeArray> extends (
    _: any,
    ...args: infer Remainder
) => any
    ? Remainder
    : never;

const DATA_KEY_PREFIX = "data-" as const;

type DataKey = `${typeof DATA_KEY_PREFIX}${string}`;

type PrependIfDataKey<
    Key extends string | number | symbol,
> = Key extends DataKey ? [Key] : [];

type DataKeys<
    Keys extends (string | number | symbol)[],
> = Keys['length'] extends 0 ? [] : [
    ...PrependIfDataKey<Head<Keys>>,
    ...DataKeys<Tail<Keys>>
];

type DataProps<Props extends Record<string, unknown>> = Pick<
    Props,
    DataKeys<(keyof Props)[]>
>;

function getDataAttributes<Props extends Record<string, unknown>>(
    props: Props,
): DataProps<Props> {
    return Object.keys(props)
        .filter((propName): propName is DataKey =>
            propName.startsWith(DATA_KEY_PREFIX),
        )
        .reduce(
            (dataProps, propName) => ({ ...dataProps, [propName]: props[propName] }),
            {} as DataProps<Props>,
        );
}


const test = { href: "#", onClick: () => null, 'data-foo': 'bar' };
const attrs = getDataAttributes(test);

Answer №1

Instead of trying to unravel your recursive types in order to appease the compiler, I suggest taking a step back and directly writing DataProps using key remapping:

type DataProps<T> = { [K in keyof T as Extract<K, DataKey>]: T[K] };

By utilizing key remapping, you can exclude properties by mapping the key to never. This is achieved through the use of the Extract<T, U> utility type to retain only keys K that are compatible with DataKey.

The functionality works effectively with your sample code:

const test = { href: "#", onClick: () => null, 'data-foo': 'bar' };
const attrs = getDataAttributes(test);

type Attrs = typeof attrs;
/* type Attrs = {
    "data-foo": string;
} */

Playground link to code

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

Current Calendar does not support interactive time input

Implementing events dynamically in a calendar using JavaScript has been quite an interesting journey for me. Here's how I have built it: Clicking a button opens a Bootstrap 4 modal. The modal contains a date range picker from daterangepicker, which ...

"Sticky Top Button That Stays in Place When Scrolling | Innovative CSS & jQuery

I've been inspired by the "Proceed to checkout" button on amazon.com and I want to recreate it. However, I'm facing a challenge as their website is not responsive and I can't find a way to view a device user agent in Chrome. To see what I&ap ...

jQuery UI Slider: Enable handles to move across each other

I have implemented a customized range slider on my webpage located at (see 'Day & Night Shift') to work with hours and minutes in 15-minute increments. $(function() { $("#slider-range").slider({ range: true, min: 0, ...

Challenge with Vite, React, and MSW Integration

Having some trouble setting up MSW in a React application. It's unusual for me to come across issues like this. I've configured an environment variable VITE_MOCK set to true when running the yarn start:mock command. This should enable API mocking ...

Transitioning away from bower in the latest 2.15.1 ember-cli update

I have been making changes to my Ember project, specifically moving away from using bower dependencies. After updating ember-cli to version 2.15.1, I transitioned the bower dependencies to package.json. Here is a list of dependencies that were moved: "fon ...

When utilizing JSON data in node.js, the .find() method may return undefined

I am currently working on a node server and my goal is to display JSON data when a specific ID is clicked. I have configured a dynamic URL that will retrieve the data of the clicked video using parameters and then compare it with the data in the JSON file ...

Can the Browser Mob Proxy capture network traffic for applications that are running on localhost?

I'm currently working on creating a tool that automatically tracks client-side performance. I recently learned that browsermob proxy combined with selenium can be used to write tests for this purpose. However, I'm curious about the possibility of ...

Locate a specific element within an array and retrieve its corresponding index

Need help updating a boolean property for all objects in an array with the same user ID. I've outlined my MVC framework below in a concise manner. Model: var posts = [{id:1, user_id:1, is_following:true}, {id:2, user_id:1, is_cool:true}, ...

Using Angular to implement a decimal pipe on an input field

I am looking for a way to display comma-separated numbers as the user types in an input field by applying the decimal pipe. I have experimented with ngx-mask, but it seems to only function when the user physically enters the numbers. However, when I manu ...

jQuery AJAX is seamlessly handling cross domain requests in Chrome and other browsers, however, it seems to be struggling in IE10 as it is not properly transmitting data. Additionally, in Internet

My web application requires sending data to an API hosted on a different domain. The API processes the received data and jQuery AJAX handles the response. This process works smoothly on Chrome and Firefox, but encounters issues on Internet Explorer. While ...

Countdown Timer in React Native

Hey, I am new to React Native and JavaScript. I want to create a simple countdown where you can input a number and select the type of countdown - whether it's in seconds, minutes, or hours. For example, if I choose 'seconds' in a dropdown an ...

What is preventing me from loading Google Maps within my Angular 2 component?

Below is the TypeScript code for my component: import {Component, OnInit, Output, EventEmitter} from '@angular/core'; declare var google: any; @Component({ selector: 'app-root', templateUrl: './app.component.html', st ...

Avoid displaying hidden images or loading content upon clicking a tab

Check out my website here I have created four tabs on my website, and I want each tab to display a different gallery (Nextgen Pro gallery) when clicked. However, the performance is currently very poor because I am loading all the images at once. I plan to ...

What are the steps to integrate TypeScript into JavaScript code?

How can I import a TypeScript class in a Node CommonJS JavaScript file? When using mongoose in my TypeScript code, I typically do the following: // user.model.ts export const UserModel = model<User>('User', schema); In my JavaScript code: ...

What is the correct method for ng-repeating through nested key-value pairs in AngularJS?

Explore the live code example: Angular JS Is there a way to effectively iterate through nested key-value pairs and display them as shown below? The desired output should resemble a tree structure like this: -touts -classes -col-12 -col-md-12 ...

Guide to dynamically formatting datetime based on the timezone

After numerous attempts to format the data, I still couldn't achieve the desired outcome in my Angular App where I am dealing with data from a database. The data looks like this: PacificTime TimeZoneCode TimeZone 2022-02-16 14:00:00.000 US/Eastern ...

Utilizing Angular Universal on an existing Express server for enhanced functionality

I have an Express server set up to host my Angular application as static content, along with other functionalities. However, I now want to integrate Server-side Rendering using Angular Universal, which requires a separate Express server just for serving th ...

Issue with accessing container client in Azure Storage JavaScript library

When working on my Angular project, I incorporated the @azure/storage-blob library. I successfully got the BlobServiceClient and proceeded to call the getContainerClient method, only to encounter this error: "Uncaught (in promise): TypeError: Failed ...

Establishing the controller to set the default order

Would appreciate some assistance with what may appear to be a beginner's question, please? This is the HTML code I'm working with: <!doctype html> <html> <head> <title>Starting Angular</title> </head> < ...

String includes another String not refreshing automatically

How come myCtrl.greeting doesn't automatically update when I change myCtrl.name? angular.module('MyApp', []) .controller('MainController', [function(){ var mCtrl = this; mCtrl.name = ''; mCt ...