Handling generic types by identifying implementation details

In the process of developing a tool, I am faced with the task of resolving generic types for the final output. It's worth mentioning that I am making use of the ts-morph library.

To illustrate, let's consider the following source code where the ClassDeclaration of classA serves as the "entry-point" for type resolution:

type X<T> = { fieldInType: T };
interface Y<T> {
  fieldInInterface: T;
}

class classB<T> {
  fieldInB?: T;
  myFunction(a: T): void { //do something here }
}

class classA extends ClassB<string> {
  interfaceField?: Y<string>;
  typeField?: X<string>;
}

The desired output should look like this:

types of classA:
   - interface Y { fieldInInterface: string } (from interfaceField)
   - type X = { fieldInType: string }  (from typeField)
   - string (from fieldInB in parentClass)
   - myFunction(a: string): void (from myFunction in parentClass) 

I am currently uncertain about the most effective way to proceed with this. At the moment, my approach involves recursively traversing all types starting from the base class (using class.getBaseClass() for recursive traversal of base classes). I believe this method is the correct and simplest approach.

Regarding generic types, my current strategy includes:

  1. Awaiting encounter with a generic type during traversal (e.g., on a class or a type-alias within the class) by verifying if it has type-arguments.
  2. If so, accessing the relevant type parameters by referencing the type definition (e.g., jumping to the base class using getBaseClass(), or the interface/alias-type using getSymbol() or getAliasSymbol()).
  3. Iterating through all type parameters and fetching the corresponding type-argument.
  4. Examining whether the type-argument itself has an entry in a map (which will be explained further ahead). If it does, substituting the type argument with the resolved type. (This step is crucial for recursively defined generics.)
  5. Maintaining a mapping for each pair, i.e., the symbol of the i-th type-parameter to the type in the type argument.

I apologize for not providing a complete code sample at this time since I have yet to finalize its implementation.

My queries are as follows:

  1. Is my current method appropriate? Or could there be a specific TypeScript compiler/ts-morph function that I may have overlooked which accomplishes the required resolution?
  2. I came across the
    typeChecker.getTypeOfSymbolAtLocation(..)
    method, but I am unsure of its exact usage and whether it can aid in my particular scenario.

Answer №1

A helpful tip would be to explore the functionalities of getTypeAtLocation and getTypeOfSymbolAtLocation.

If you take a look at the example provided on ts-ast-viewer.com, then you can run the following code snippet in your developer console:

{
    const classANode = sourceFile.statements[3];
    const classAType = checker.getTypeAtLocation(classANode);
    for (const prop of classAType.getProperties()) {
        const type = checker.getTypeOfSymbolAtLocation(prop, classANode);
        console.log(prop.escapedName, checker.typeToString(type));
    }
}

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

Using @Input to pass data from a parent component to a

Looking to modularize the form code into a separate component for reusability? Consider using @Input and referencing it in the HTML to pass values to the post method. Here's how you can achieve this: Previously, everything worked smoothly when all th ...

Incorporate a service into a base class in Angular2 to ensure its functionality extends to all derived classes

I have multiple classes with a hierarchical inheritance structure as follows: class A (an abstract class) class B extends A class C extends B I am looking to incorporate a service into class A to enable a function that utilizes notifications. How can I ...

Leverage Angular's interpolation feature to display data in tippy-content

Currently, I am working on an Angular project and successfully implemented tippy.js, which you can find working perfectly at this link: . However, the issue arises when I attempt to populate the tooltips with JSON data using Angular's interpolation. ...

Can triggering an ngrx effect lead to memory leakage?

Currently, I am delving into the world of NgRx and grappling with a concept that has been puzzling me. As I create an Effect and dispatch an action, the createEffect function comes into play. What throws me off is the dispatch configuration within createEf ...

A guide on utilizing the useEffect hook to dynamically update a button icon when hovering over it in a React application

Is it possible to change the icon on a button when hovering using useEffect? <Button style={{ backgroundColor: "transparent" }} type="primary" icon={<img src={plusCart} />} onCl ...

Encountering a NullInjectorError in Angular while utilizing dynamic module federation when importing a standalone component along with

My main goal is to develop a shell application acting as a dashboard without routing, featuring multiple cards with remote content (microfrontend standalone component). I have been following a tutorial that aligns closely with my requirements: . The reas ...

Typescript does not support index signatures with bracket property accessor when importing using the `import * as`

Currently learning typescript and in the process of converting a large program from javascript. While fixing errors and adding types, I'm stuck on this one particular issue. Here's myModule.ts: export const foo = { ... } export const bar = { .. ...

An error occurs when implementing the RxJS partition operator in combination with Angular

Extracting data in ngOnInit hook: ngOnInit(): void { var routeParameters = zip( this._route.parent.paramMap, this._route.paramMap ).pipe( map(([parentMap, currentMap]) => ({ customerID: parentMap.get('id'), siteID: currentMap. ...

Uncovering the Mutable Object Type within an Immutable Object

I would like to create a type that specifically extracts the mutable object type from an existing immutable object type like such: import * as Immutable from 'seamless-immutable' interface IObjType { field: string; } type TObjImmType = Immuta ...

Is it possible to dynamically adjust the size of the CircleProgressComponent element in ng-circle-progress?

For my current Angular 11 project, I am facing the challenge of dynamically changing the size of the ng-circle-progress library's CircleProgressComponent element. After some research, I discovered that the element's size can be adjusted by apply ...

Unable to assign a value to an undefined property in TypeScript

I need to store data in an object and then add it to another object let globalSamples = {} as any; let sample = { } as ISamplesDetail []; sample = []; for (let i = 0 ; i<this.prelevementLingette.samplesDetail.length; i++) { sample [i].id= thi ...

What is the method to assert that two arguments are equal within a function?

When working with TypeScript, you can pass a value to a function and have that function assert the value is true for type narrowing. For example: function assertTrue(v: unknown, message: string): asserts v { if (!v) { throw new MySpecialError(message ...

Utilize TypeScript File array within the image tag in HTML with Angular 2

I am in the process of developing a web application that allows users to upload CSV data and images, which are then displayed on the application. However, I have encountered an issue where I am unable to display the imported images. The images are imported ...

Sequencing API Calls: A Guide on Making Sequential API Requests

Currently, I am working on mastering RxJS. Within my project, there are 3 API calls that need to be made. Specifically, I must execute the 2nd API call and then pass its data as a parameter to the 3rd API call. My attempt at achieving this functionality is ...

What could be the root of this next.js build issue occurring on the Vercel platform?

I recently upgraded my next.js project to version 12.0.7, along with Typescript (4.5.4) and pdfjs-dist (2.11.228), among other libraries. Locally, everything runs smoothly with the commands yarn dev for development and yarn build for building. However, af ...

Different approaches for implementing custom type guards?

I've been studying User-Defined Type Guards in the Typescript handbook. Imagine you have a union type that needs to be narrowed down like this: interface Bird{ fly(); layEggs(); } interface Fish{ swim(); layEggs(); } class SmallPet ...

Troubleshooting Angular MIME problems with Microsoft Edge

I'm encountering a problem with Angular where after running ng serve and deploying on localhost, the page loads without any issues. However, when I use ng build and deploy remotely, I encounter a MIME error. Failed to load module script: Expected a ...

Error: Uncaught TypeError - The function indexOf is not defined for e.target.className at the mouseup event in HTMLDocument (translator.js:433) within the angular

Upon clicking on an SVG to edit my data in a modal bootstrap, I encountered the following error: Uncaught TypeError: e.target.className.indexOf is not a function at HTMLDocument.mouseup (translator.js:433) This is my SVG code: <svg data-dismiss ...

I'm having trouble setting a value for an object with a generic type

I am attempting to set a value for the property of an object with generic typing passed into a function. The structure of the object is not known beforehand, and the function receives the property name dynamically as a string argument. TypeScript is genera ...

How can I retrieve only the pertinent information stored in Firestore?

I'm struggling to filter out only the data relevant to a specific "userId" from Firestore, as currently everything in the database is being printed. I've attempted to make changes based on advice I received but it hasn't resulted in any impr ...