Exploring Typescript Reflection: The Importance of Required Parameters and Default Values

In summary: Is there a method to determine whether a typescript parameter is mandatory and/or has a preset value?

Expanding further: Imagine I have the code snippet below:

//Foo.ts
class Bar {
    foo(required:string,defaultValue:number=0,optional?:boolean) {
        ...
    }
}

I am interested in retrieving the following details for each parameter:

  • The name
  • The data type
  • Is it obligatory?
  • Does it come with a default value?

While I have effectively utilized method decorators alongside the TypeScript reflection API to obtain the data types of the parameters, as well as referenced this approach to retrieve their names, I have not yet discovered a technique to identify if a parameter is mandatory or has a default value.

I acknowledge that the typescript compiler can be accessed from within typescript itself. Therefore, I am curious if there exists a means to utilize the parse tree of the compiler to ascertain whether a parameter is compulsory and/or has a predefined value?

How would this process unfold?

Answer №1

If you're looking to start from scratch...

At a high level, one approach is:

  1. Determine how to obtain the SourceFile node using your file's compiler API, which entails some explanation.

  2. Utilize the API's forEachChild function to iterate through all nodes in the file and locate the node with a kind of SyntaxKind.ClassDeclaration and a .name property containing the text Bar.

  3. Subsequently, iterate through all the class's children by employing the API's forEachChild function again, identifying those with a kind of SyntaxKind.MethodDeclaration and a .name property holding the text foo.

  4. To access the parameters, loop over the method node's parameters property.

  5. For each parameter node, retrieve the name by calling .getText() on the .name property.

  6. Determine if the parameter is optional by:

     const parameterDeclaration = parameterNode as ts.ParameterDeclaration;
     const isOptional = parameterDeclaration.questionToken != null || parameterDeclaration.initializer != null || parameterDeclaration.dotDotDotToken != null;
    

    Alternatively, utilize the TypeChecker's isOptionalParameter method.

  7. To find its default expression, simply inspect the initializer property:

    propertyDeclaration.initializer;
  8. To determine the type, employ the TypeChecker's getTypeOfSymbolAtLocation method and provide the symbol of the node... this can get complex due to variations with union types, so I won't delve into it further.

Avoid starting from scratch...

I've developed a wrapper for the TypeScript compiler API. Simply use this code snippet with ts-simple-ast (note: Previously mentioned my previous ts-type-info library, but ts-simple-ast is more robust):

import { Project } from "ts-morph";

// explore setup details here:
// https://ts-morph.com/setup/adding-source-files
const project = new Project({ tsConfigFilePath: "tsconfig.json" });
const sourceFile = project.getSourceFileOrThrow("src/Foo.ts");
const method = sourceFile.getClassOrThrow("Bar").getInstanceMethodOrThrow("foo");

Once you have the method, gathering necessary information from its parameters is straightforward:

console.log(method.getName()); // foo

for (const param of method.getParameters()) {
    console.log(param.getName());
    console.log(param.getType().getText());
    console.log(param.isOptional());
    console.log(param.getInitializer() != null);
}

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

Retrieve user roles from core in Angular prior to implementing a guard

Hey, I'm facing an issue with my app.module setup. I have implemented lazy loading to load the core module and store roles in the core component. Everything works fine when I navigate from one page to another with the role guard applied. However, when ...

Combining Rxjs map and filter to extract countries and their corresponding states from a JSON dataset

I have a unique dataset in JSON format that includes information about countries and states. For example: { "countries": [ { "id": 1, "name": "United States" }, { "id": 2, "name": "India" }], "states": [ { ...

I'm encountering an issue in my node application where it is unable to access the push

I am a beginner in the world of node.js and express. Whenever I try to start my application using the command npm start, I encounter an error message saying Cannot Read property push of undefined from my index.js file. The problematic code snippet looks l ...

Application: The initialization event in the electron app is not being triggered

I am facing an issue while trying to run my electron app with TypeScript and webpack. I have a main.ts file along with the compiled main.js file. To troubleshoot, I made some edits to the main.js file to verify if the "ready" function is being called. ...

What is the solution for resolving this Angular issue: Expected argument expression.ts(1135)?

While following a CRUD tutorial, I encountered an issue with the code. Even though I have verified that my code matches the tutorial's code, I am getting an error message saying "Argument expression expected. ts(1335)" in the submit method onSubmit(). ...

Learn how to effectively declare data as global within Angular2 or Typescript

I am facing an issue with fetching the id inside the Apiservice despite being able to get it in the console. Can anyone provide assistance on how to solve this problem? TS: deleteProduct(index,product) { var token = this.auth.getAccessTokenId(); ...

Navigating to the detail page following a POST request in RTK query: A step-by-step guide

In my React RTK-query form, I am facing an issue where after a POST request is made, the form should navigate to the next step. However, in order to do that, I need to obtain the id of the newly created record. The backend auto-increments the id and does n ...

The function e.preventDefault() appears to be ineffective when applied to both the submit button and anchor tag within an

In my ASP.Net Core MVC App View <form> <div class="container"> <div class="row"> <div class="col-md-offset-2 col-md-4"> <div class="form-group"> <input type="text" class="form-contr ...

Changing dot notation to bracket notation in Angular

Having trouble using dynamic columns in a Primeng table? The column fields need to be in bracket notation for this setup. What if you have a column with nested JSON structure and you're not sure how to write that in bracket notation? Don't worry, ...

Leveraging Javascript Modules within a Typescript Vue Application

The issue at hand I've encountered a problem while attempting to integrate https://github.com/moonwave99/fretboard.js into my Vue project. My initial approach involved importing the module into a component as shown below: <template> <div&g ...

Best Practices for Organizing Imports in Typescript to Prevent Declaration Conflicts

When working with TypeScript, errors will be properly triggered if trying to execute the following: import * as path from "path" let path = path.join("a", "b", "c") The reason for this error is that it causes a conflict with the local declaration of &ap ...

Angular Error TS2339: The property 'car' is missing from type 'Array of Vehicles'

Encountering Angular Error TS2339: Property 'vehicle' is not found on type 'Vehicle[]'. The error is occurring on data.vehicle.results. Any thoughts on what could be causing this issue? Is the problem related to the Vehicle model? I hav ...

group items into ranges based on property of objects

I've been grappling with this issue for far too long. Can anyone provide guidance on how to tackle the following scenario using JavaScript? The dataset consists of objects representing a date and a specific length. I need to transform this list into a ...

After successfully building with Vite, an error occurs stating "TypeError: can't convert undefined to object." However, during development with Vite, everything functions flawlessly

Currently, I am utilizing Vite in conjunction with React and Typescript for my project. Interestingly, when I execute 'vite dev', the live version of the website works flawlessly without any errors showing up on the console. However, things take ...

Typescript parameters provide specific data types for functions that can accept either a single argument or two arguments, such as Element.scrollBy

One question I have is how to access the options parameter in the scrollBy() method. Parameters<Element["scrollTo"]> When I use [x: number, y: number] as per the documentation, it does not include options?: ScrollToOptions. scrollTo(option ...

Is it acceptable to use JavaScript files in the pages directory in NEXTJS13, or is it strongly advised to only use TypeScript files in the most recent version?

In the previous iterations of nextJS, there were JavaScript files in the app directory; however, in the most recent version, TypeScript files have taken their place. Is it still possible to begin development using JavaScript? I am working on creating an a ...

What are the advantages of utilizing the HttpParams object for integrating query parameters into angular requests?

After exploring different ways to include query parameters in HTTP requests using Angular, I found two methods but struggled to determine which one would be the most suitable for my application. Option 1 involves appending the query parameters directly to ...

Guide to accessing component methods within slots using the Vue 3 Composition API

I have child components within a slot in a parent component and I am trying to call methods on them. Here are the steps I followed: Use useSlots to retrieve the child components as objects Expose the method in the child component using defineExpose Call t ...

strictNullChecks and the dissemination of null values

Considering implementing the strictNullChecks flag in a large code base presents some challenges. While it is undeniably a valuable tool, the abundance of null types in interface definitions may be impacting the code's readability. This is particularl ...

"Error: Variable becomes undefined due to the implementation of async-await in TypeScript

There has been a persistent issue I've been dealing with for some time now. The problem lies in the fact that vm_res is undefined within the async update_vm_raw_device function despite the function running smoothly. As a result, the value being update ...