Reputation: 371
While implementing the client side of a server communication I happen to meet the following problem: How can I store a reference to an interface in a variable.
I have an interface that hold all the information about a specific RESTfull backend call:
export interface IEndpoint {
path: string,
method: HTTP_METHOD,
data: any,
response: any
}
Create instance of this element (ISomeInterface and IAnotherInterface are the interfaces that I want to refer to later):
export const GET_TEST: IEndpoint = {
path: 'api/test',
method: HTTP_METHOD.GET,
data: <ISomeInterface>{},
response: <IAnotherInterface>{}
};
The goal is to use the data and response field as type references in a Promise (meta is an instance of IEndpoint):
new Promise<meta.response>((resolve) => {
...
});
The callback type of the Promise (meta.response) is where I am not able to extract the type/interface that I previously assigned.
Upvotes: 3
Views: 6191
Reputation: 249586
Values and types exist in two different domains. Types are erased at compile time so we can't assign a type to an interface field as you try to do.
What we can do is work in the type domain and keep the data
and response
types in the IEndpoint
type using generic parameters, and extract them when needed.
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);
As @jeroen-vervaeke points out makeRequest
could also be typed in a simpler way with the same effect:
function makeRequest2<TData, TResponse>(endPoint: IEndpoint<TData, TResponse>, data: TData): Promise<TResponse>{
return null as any;
}
Upvotes: 3
Reputation: 3436
You refer to meta
part in:
new Promise<meta.response>((resolve) => {
...
});
As it would represent a type, while it represent's a value. You can workaround it by using typeof
:
new Promise<typeof (meta.response)>((resolve) => {
...
});
Or via direct reference to response type:
new Promise<IAnotherInterface>(resolve => {
...
});
Beside that, TS team strongly suggest to use as
as casting operator, not <>
:
export const GET_TEST: IEndpoint = {
path: 'api/test',
method: HTTP_METHOD.GET,
data: {} as,ISomeInterface
response: {} as IAnotherInterface
};
Upvotes: -1
Reputation:
You could work around your issue with a generic class and bind the method to this class :
export class Endpoint<T, U> {
constructor(
private path: string,
private method: HTTP_METHOD,
private data: T,
private response: U
) {}
// your new promise method there
}
Upvotes: 0