Búsqueda de sitios web

angular - Typescript: referencia a interfaz en variable


Mientras implementaba el lado del cliente de una comunicación con el servidor, me encontré con el siguiente problema: ¿Cómo puedo almacenar una referencia a una interfaz en una variable?

Tengo una interfaz que contiene toda la información sobre una llamada específica a un backend RESTful:

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

Crear instancia de este elemento (ISomeInterface e IAnotherInterface son las interfaces a las que quiero referirme más adelante):

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

El objetivo es usar los campos de datos y respuesta como referencias de tipo en una Promesa (meta es una instancia de IEndpoint):

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

El tipo de callback de la Promise (meta.response) es donde no puedo extraer el tipo/interfaz que asigné previamente.

Respuesta #1

Los valores y los tipos existen en dos dominios diferentes. Los tipos se eliminan en tiempo de compilación, por lo que no podemos asignar un tipo a un campo de interfaz como intentas hacer.

Lo que podemos hacer es trabajar en el dominio de tipos y mantener los tipos data y response en el tipo IEndpoint usando parámetros genéricos, y extraerlos cuando sea necesario.

export interface IEndpoint<TData, TResponse> {
    path: string,
    method: HTTP_METHOD,
    // just here because typescript doesn't handle unused generics well
    _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"
};
// Takes in ISomeInterface returns Promise<IAnotherInterface> 
makeRequest(GET_TEST, { data: ""}).then(r=> r.result);

Como señala @jeroen-vervaeke, makeRequest también podría escribirse de una manera más simple con el mismo efecto:

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

Respuesta #2

Podrías solucionar tu problema con una clase genérica y enlazar el método a esta clase:

export class Endpoint<T, U> {
  constructor(
    private path: string,
    private method: HTTP_METHOD,
    private data: T,
    private response: U
  ) {}

  // your new promise method there
}