Using Typescript: storing a reference to an interface within a variable

During the implementation of client-side server communication, I encountered a particular challenge: How can I store a reference to an interface in a variable?

I have defined an interface that contains all the details related to a specific RESTful backend call:

export interface IEndpoint {
  path: string,
  method: HTTP_METHOD,
  data: any,
  response: any
}

To create instances of this interface (ISomeInterface and IAnotherInterface are the interfaces I want to reference later), I do the following:

export const GET_TEST: IEndpoint = {
  path: 'api/test',
  method: HTTP_METHOD.GET,
  data: <ISomeInterface>{},
  response: <IAnotherInterface>{}
};

The objective is to use the data and response fields as type references in a Promise (where meta is an instance of IEndpoint):

new Promise<meta.response>((resolve) => {
  ...
});

The issue arises when trying to extract the type/interface previously assigned for the callback type of the Promise (meta.response).

Answer №1

In the realm of programming, values and types reside in distinct domains. During compile time, types are eliminated, preventing us from assigning a type to an interface field as attempted.

One approach is to operate within the type domain by incorporating data and response types within the IEndpoint type using generic parameters, which can be extracted when necessary.

export interface IEndpoint<TData, TResponse> {
    path: string,
    method: HTTP_METHOD,
    // included to address TypeScript's handling of unused generics
    _data?: TData,
    _response?: TResponse
}

function makeRequest<T extends IEndpoint<any, any>>(endPoint: T, data: T['_data']): Promise<T['_response']> {
    return null as any// actual call
}

interface ISomeInterface { data: string }
interface IAnotherInterface { result: string }
export const GET_TEST: IEndpoint<ISomeInterface, IAnotherInterface> = {
    path: 'api/test',
    method: "GET"
};
// Receives ISomeInterface and returns a Promise<IAnotherInterface>
makeRequest(GET_TEST, { data: ""}).then(r=> r.result);

As @jeroen-vervaeke highlights, makeRequest could also be simplified without altering its effect:

function makeRequest2<TData, TResponse>(endPoint: IEndpoint<TData, TResponse>, data: TData): Promise<TResponse>{
    return null as any;
}

Answer №2

If you're facing difficulties, you can overcome them by using a generic class and associating the method with this particular class:

export class ServiceEndpoint<X, Y> {
  constructor(
    private endpoint: string,
    private action: HTTP_ACTION,
    private input: X,
    private output: Y
  ) {}

  // Implement your new promise method here
}

Answer №3

When mentioning the meta portion, it is important to note:

new Promise<typeof meta.response>((resolve) => {
  ...
});

Instead of considering it as a type, recognize it as a value. An alternative approach is to utilize typeof:

new Promise<typeof (meta.response)>((resolve) => {
  ...
});

Alternatively, you can directly reference the response type:

new Promise<IAnotherInterface>(resolve => {
  ...
});

In addition, the TypeScript team recommends using as for casting instead of <>:

export const GET_TEST: IEndpoint = {
  path: 'api/test',
  method: HTTP_METHOD.GET,
  data: {} as ISomeInterface,
  response: {} as IAnotherInterface
};

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

Angular 6 Time Discrepancy

I am trying to display real-time time difference on the UI that updates every second. Here is what I have attempted: component.ts import { Component, OnInit } from '@angular/core'; import 'rxjs/add/observable/of'; import 'rxjs/a ...

A guide on implementing nested child routes in AngularJS 2

I have successfully completed routing for two children, but now I want to display nested routes for those children. For example: home child1 child2 | grand child | grand child(1) ...

What is the method of including a null option in a dropdown menu?

I have a basic dropdown menu with the placeholder text "none." I want users to be able to clear their selection without adding another option to the dropdown. Can anyone help me achieve this? Thank you! Below is my code snippet: Check out the live demo h ...

Tips for overflowing an image within an Ionic toolbar

I am attempting to adjust the image overflow within the toolbar using the following code: ion-header { background: var(--ion-color-primary); ion-toolbar { --padding-end: 30px; --padding-start: 30px; --min-height: 100px; ion-avatar ...

How can I make sure that the combobox in my Ionic app is aligned with the text fields in a row?

From the image provided, it's evident that my HTML code looks like this: <ion-row> <ion-col> <ion-item> <searchable-ion-select isModal="true" name="country" valueField="code" [(ngModel)]="country" title="Country" ...

Fetching JSON data from a Node.js server and displaying it in an Angular 6 application

Here is the code snippet from my app.js: app.get('/post', (req,res) =>{ let data = [{ userId: 10, id: 98, title: 'laboriosam dolor voluptates', body: 'doloremque ex facilis sit sint culpa{ userId: 10' ...

Angular Observable being triggered repeatedly

In my service, I have implemented a global observable in the following way: @Injectable() export class XYZService { country: Observable<any>; isBrowser: boolean; constructor(private http: Http, private httpClient: Htt ...

Retrieving data from Node.js within an Angular application

I am currently working on retrieving data from MongoDB and displaying it on my website. However, I am facing an issue in sending the entire fetched object to a specific port (the response) so that I can retrieve it from Angular. I also need to know how to ...

Determining the Type<> of a component based on a string in Angular 2

Can you retrieve the type of a component (Type<T>) based on a string value? For example: let typeStr: string = 'MyComponent'; let type: any = getTypeFromName(typeStr); // actual type ...

Setting a variable in Angular after a successful AJAX call

Working on a new small application and experimenting with Angular. Encountering an issue where I am making an AJAX GET request upon clicking a button. After receiving the response, I want to set a variable to hold the result, but for some reason the variab ...

A guide on utilizing server-based data grouping and showcasing it in ag-grid within an angular environment

Is there a way to organize the data based on the server name, which is identified by the object key server? The code snippet below illustrates the structure of the data: rowData = [ { server: "Server 1", ping: "10 ms", ...

Utilize Lambda Layer to seamlessly share interfaces/types across Lambda Functions

I have a lambda layer file that contains an enum definition (which will be used in various lambda functions) as shown below: exports enum EventTypes { Create, Delete, Update, } Initially, everything was working well as I tested ...

Guide to sending a request to a third-party API using Node.js and Express.js with the 'Authorization: Basic' header

Attempting to utilize the UDEMY API, each request necessitates the inclusion of Authorization: Basic + keys header. The API documentation specifies: curl --user {YOUR_CLIENT_ID}:{YOUR_CLIENT_SECRET} https://www.udemy.com/api-2.0/courses/ curl -H "Au ...

What is the correct way to install @angular-devkit/build-angular in Angular version 13?

In my Angular 13 project, I am facing a dilemma with conflicting dev dependencies: "devDependencies": { "@angular-devkit/build-angular": "~13.2.5", "@angular/cli": "~13.2.5", "@angular/co ...

Using Typescript with Momentjs: 'String type cannot be assigned to Date type'

Up until now, my approach to utilizing the momentjs library was as follows: import * as moment from 'moment'; // import moment. @Component({..}); export class TestClass { lastUpdated = Date constructor(private myService: MyService){ this ...

Utilizing Nativescript Angular, personalize the styling by separating the SCSS file into two distinct platform-specific SCSS files labeled as .android.scss and .ios

After modifying my component to convert it into a nativescript angular platform specific SCSS, everything seems to be working fine. The button's background turns yellow on the android platform/simulator and green on IOS, as specified in the SCSS files ...

A method for increasing a counter using only an instance of a class or function without accessing its methods or properties in Javascript

Looking at the task ahead, let increment = new Increment(); I have been tasked with creating a Javascript class or function called Increment in order to achieve the following: console.log(`${increment}`) // should output 1 console.log(`${increment}`); ...

I have a quick question: What is the most effective method for creating PDF templates with Angular and .NET 6, specifically for designs that feature heavy

Seeking the optimal solution for creating PDF templates using Angular and .NET 6? Specifically looking to design templates that heavily feature tables. In my exploration of efficient PDF template creation with Angular and .NET 6, I ventured into using pdf ...

Setting up ESM for Firebase functions: A step-by-step guide

Our server application needs to utilize the most recent ipfs-http-client as it is an authorized package for accessing IPFS. However, the project must switch to using ESM starting from v57.0.0. I have invested a significant amount of time into this and it h ...

`Obtaining information from a single JSON object`

Here is the code snippet I'm working with: ng-repeat="item in records" {{item.listingname}} Encountered an error: Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. To resolve this, use a 'track by' expression to specify ...