Reputation: 1017
I have a function that is a wrapper for axios.request
.
I send a Message type along with config so that I can create a new Message with the response.data
.
I have multiple types of Messages, so I am creating a generic TMessage
type to handle this:
public request<TMessage extends BaseMessage<TMessage>>(
config: Axios.AxiosXHRConfig<any>,
messageType: {new (message: string): TMessage}
): Promise<TMessage> {
return new Promise((resolve, reject) => {
axios.request(config).then((response: Axios.AxiosXHR<any>) => {
try {
let message = new messageType(response.data);
resolve(message);
} catch (err) {
reject(err);
}
}, reject);
});
}
I can now request with a message type and know what type of response I am getting:
RestClient.request(config, SomeMessage).then((response: SomeMessage) => {
// response is of type SomeMessage, I have intellisense to help
resolve(response);
});
I want to make this messageType optional, as some requests don't have a useful response and don't need to be instantiated into a new message.
Is there a way in TypeScript to do this? The following code uses Union Types and compiles, but it does not enforce the messageType to match the return type, making it a bit redundant.
I want a Promise<TMessage>
return type if messageType is supplied. Otherwise I want a Promise<Axios.AxiosXHR<any>>
return type
public request<TMessage extends BaseMessage<TMessage>>(
config: Axios.AxiosXHRConfig<any>,
messageType?: {new (message: string): TMessage}
): Promise<TMessage | Axios.AxiosXHR<any>> {
...
-
RestClient.request(config, SomeMessage).then((response: OtherMessage) => {
// this compiles, ideally it should complain about the mismatch of message types
resolve(response);
});
Upvotes: 4
Views: 1583
Reputation: 164129
You can define different signatures for the method:
public request<TMessage extends BaseMessage<TMessage>>(
config: Axios.AxiosXHRConfig<any>,
messageType: {new (message: string): TMessage}
): Promise<TMessage>;
public request(
config: Axios.AxiosXHRConfig<any>
): Promise<Axios.AxiosXHR<any>>;
public request<TMessage extends BaseMessage<TMessage>>(
config: Axios.AxiosXHRConfig<any>,
messageType?: {new (message: string): TMessage}
) {
...
}
This feature is described in the Overloads part of the docs:
JavaScript is inherently a very dynamic language. It’s not uncommon for a single JavaScript function to return different types of objects based on the shape of the arguments passed in
More info in the link.
Upvotes: 6