Using TypeScript to fetch properties from a class in a recursive manner

I'm having trouble utilizing the solution provided in this response to exclude functions when invoking the set method with class fields, as it results in the error message

Type instantiation is excessively deep and possibly infinite.
. I came across this inquiry, but using // @ts-ignore isn't an option due to compromising type safety. The recommended approach in that post also doesn't seem applicable in my case. Additionally, I found this related discussion, but the implementation details are unclear to me, likely because of my limited understanding of TS recursive generics. How can I retrieve field properties recursively while excluding functions and considering whether the fields are optional or not, without encountering the excessively deep error?

Please note: there may be additional issues present in the linked code, so I'm hoping for assistance from a seasoned TypeScript expert to address them.

Access the Fiddle and review the following code:

// types taken from https://stackoverflow.com/a/62362197/1253609
type IfEquals<X, Y, A=X, B=never> =
  (<T>() => T extends X ? 1 : 2) extends
  (<T>() => T extends Y ? 1 : 2) ? A : B;

type WritableKeys<T> = {
  [P in keyof T]: T[P] extends Function ? never : IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, P>
}[keyof T];

type DeepWritablePrimitive = undefined | null | boolean | string | number | Function;
type DeepWritable<T> =
    T extends DeepWritablePrimitive ? T :
    T extends Array<infer U> ? DeepWritableArray<U> :
    T extends Map<infer K, infer V> ? DeepWritableMap<K, V> :
    T extends Set<infer T> ? DeepWriableSet<T> : DeepWritableObject<T>;

type DeepWritableArray<T> = Array<DeepWritable<T>>;
type DeepWritableMap<K, V> = Map<K, DeepWritable<V>>;
type DeepWriableSet<T> = Set<DeepWritable<T>>;

type DeepWritableObject<T> = {
    [K in WritableKeys<T>]: DeepWritable<T[K]>
};

class Base {
  set(data?: Partial<DeepWritable<typeof this>>) {
    Object.assign(this, data);
  }
}

class Parent extends Base {
  name?: string;
  arr?: Parent[];
};

const record = new Parent();
record.set({
  // https://github.com/microsoft/TypeScript/issues/34933
  arr: [{
    name: '0'
  }]
})
console.log(record.arr);

Answer №1

Recursion issue potentially related to Map, adding a check for Map<any, any> as the first step appears to resolve it.
It seems like some keys were overlooked, resulting in lost optionality.

type DeepWritable1<T> =
  | T extends DeepWritablePrimitive ? T
  : T extends (infer U)[] ? DeepWritable1<U>[]
  : T extends Map<any, any> ? (
    T extends Map<infer K, infer V> ? Map<K, DeepWritable1<V>> : never
  )
  : T extends Set<infer V> ? Set<DeepWritable1<V>>
  : DeepWritableRecord1<T>;

type DeepWritableRecord1<T> = {
  // Optionality preservation is necessary here
  [K in keyof Pick<T, WritableKeys<T>>]: DeepWritable1<T[K]>
}

Explore more details here

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

Continue looping in Javascript until an empty array is identified

Currently, I am in search of a solution to create a loop in Javascript that continues until the array of objects is empty. The object I am working with looks like this: "chain": { "evolves_to": [{ "evolves_to": [{ ...

Docusaurus font loading specifically optimized for body text, excluding headings

I've added the following CSS code to my Docusaurus custom stylesheet: @import url("https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&display=swap"); :root { --ifm-color- ...

What is the best way to access a class's private static property in order to utilize it for testing purposes?

Hello, I am currently a beginner in TypeScript and unit testing, so this inquiry may seem elementary to those more experienced. I am attempting to perform unit testing on the code provided below using sinon. Specifically, I am interested in testing whethe ...

Utilizing an External Variable in a Callback Function in Node.js / Express.js

Currently, I am utilizing a library known as node-geocoder within express js with the code snippet provided below: var NodeGeocoder = require('node-geocoder'); var options = { provider: 'google', // Additional values may be nece ...

retrieving data from a dropdown selection

Help! I'm stuck and need guidance. Below is the code I've been working on, attempting to set a variable using a drop-down list. Despite trying everything I can think of, I still seem to be missing something simple. Any hints or nudges in the righ ...

Top method for identifying genuine users and preventing bots

Utilizing a Maps API can be costly, especially with the fees per request To minimize requests, I heavily rely on caching techniques The API is invoked on every pageload, but unnecessary for non-human users like googlebot What would be the most effective ...

Enhance Material UI with custom properties

Is it possible to add custom props to a Material UI component? I am looking to include additional props beyond what is provided by the API for a specific component. For example, when using Link: https://material-ui.com/api/link/ According to the document ...

Looking for assistance with arranging and managing several containers, buttons, and modals?

My goal is to create a grid of photos that, when hovered over, display a button that can be clicked to open a modal. I initially got one photo to work with this functionality, but as I added more photos and buttons, I encountered an issue where the first b ...

Slider Jquery - Displaying Half-Step Visual Bar Lengths

JSFIDDLE $(function() { $( "#slider-range-min" ).slider({ range: "min", value: 5, min: 0, step: .5, max: 10, slide: function( event, ui ) { $( "#amount" ).val(ui.value); ...

Switch Parent Element's Class

I am facing an issue with my web application where I need to dynamically change the background color of certain cells in a table based on their stored values. After searching online for JavaScript and jQuery solutions, I have not been able to find exactly ...

How can I convert base64 data to a specific file type using React Cropper JS?

I have successfully implemented the crop functionality using react cropper js. Now, I am faced with a challenge of sending the cropped image as a file type. Currently, I can obtain the base64 string for the cropped image. However, when I submit the cropped ...

The buttons on the Bootstrap Carousel are unresponsive and the indicators are not displaying as they should

I am currently attempting to replicate a bootstrap carousel that includes indicators. However, in my code, I am unable to view the indicators, and the previous/next buttons are not functional. Although I came across a workaround that I could modify from th ...

How can you retrieve a value in NodeJS Promise (Q) even when the promise fails?

As I dive into the world of promises in my NodeJS projects, I encountered a challenging situation. Despite reading the Promises/A+ spec and conducting extensive searches online, I struggled to find an elegant solution for accessing a value generated within ...

Adjusting the styling of a webpage in real-time

Here is the CSS code I am working with: .myTabs .JustForFun .ajax__tab_inner:hover { width: 109px; background: url ("/images/csc_tr.png") no-repeat 100% 0%; margin-right: 2px; background-color: #BBC614; } I want to change the background-c ...

Codify the mathematical operation using Typescript

While working on my Angular 2 project with TypeScript, I encountered an issue where I am attempting to send an arithmetic operation such as 2+4 through an http get request. The expected response from the back-end should be 6. However, the problem arises w ...

What is the best way to align content in the left center of a Paper component and ensure it stays that way on smaller devices?

Recently, I've been developing a component for my Goal Sharing social media platform. Here's what I have accomplished so far: https://i.stack.imgur.com/UDRim.png In an attempt to position the Avatar component along with two typography component ...

Leveraging Angular 2's HTTP client functionality with ES5 syntax

We are in the process of upgrading our Angular 1 application to Angular 2, module by module. Since our current project is built on es5, we have decided to stick with it while transitioning to Angular 2. We have a good understanding of upgradeAdapter and DI ...

Iterate through an object, with certain keys being duplicated

Currently, I am facing a scenario where the object I'm analyzing is quite messy... Essentially, within this object... my goal is to locate the pageviews node, but only if it has an array of data... Here's an example of the data: data = [ ...

Navigating to an anchor link within an HTML document using React Router DOM in ReactJS

Currently in the process of building an application that includes patch notes, I have defined URL structures using React Router as shown below: <Route path="/updates/:id?" render={(params) => <Updates {...params} />} /> I am looking to imp ...

Storing a string in localStorage versus $localStorage in Angular 1 yields distinct value differences

I have encountered an issue in my angular controller where I am trying to save a token returned from an API endpoint as a string. In this example, I have used the variable testData instead of the actual token. var testData = "testdata" $localStorage[&apo ...