Wrote up some custom TypeDefs for your question.
- First, write your function as a TypeScript Class, one that accepts a generic argument (T). In this way, you can apply a constraint (T) on a class which the Mixin is applied to
type FetcherConstructor<T = {}> = new (...args: any[]) => T;
- Our class only works if the url parameter is passed a string value -- the required url parameter is an example of implementing an applied constraint (mentioned above)
type FetcherAbstracted = FetcherConstructor<{
fetcher: (url: string, init?: RequestInit) => Promise<Response>;
}>;
As you can see, the conditional RequestInit interface is quite extensive
interface RequestInit {
/**
* A BodyInit object or null to set request's body.
*/
body?: BodyInit | null;
/**
* A string indicating how the request will interact with the browser's cache to set request's cache.
*/
cache?: RequestCache;
/**
* A string indicating whether credentials will be sent with the request always, never, or only when sent to a same-origin URL. Sets request's credentials.
*/
credentials?: RequestCredentials;
/**
* A Headers object, an object literal, or an array of two-item arrays to set request's headers.
*/
headers?: HeadersInit;
/**
* A cryptographic hash of the resource to be fetched by request. Sets request's integrity.
*/
integrity?: string;
/**
* A boolean to set request's keepalive.
*/
keepalive?: boolean;
/**
* A string to set request's method.
*/
method?: string;
/**
* A string to indicate whether the request will use CORS, or will be restricted to same-origin URLs. Sets request's mode.
*/
mode?: RequestMode;
/**
* A string indicating whether request follows redirects, results in an error upon encountering a redirect, or returns the redirect (in an opaque fashion). Sets request's redirect.
*/
redirect?: RequestRedirect;
/**
* A string whose value is a same-origin URL, "about:client", or the empty string, to set request's referrer.
*/
referrer?: string;
/**
* A referrer policy to set request's referrerPolicy.
*/
referrerPolicy?: ReferrerPolicy;
/**
* An AbortSignal to set request's signal.
*/
signal?: AbortSignal | null;
/**
* Can only be null. Used to disassociate request from any Window.
*/
window?: any;
}
- Where the bodyInit type is defined as follows
type BodyInit = Blob | BufferSource | FormData | URLSearchParams | ReadableStream<Uint8Array> | string;
- And the
Response interface, which is typeof fetcher in this example, has the following response interface as its returned payload
/** This Fetch API interface represents the response to a request. */
interface Response extends Body {
readonly headers: Headers;
readonly ok: boolean;
readonly redirected: boolean;
readonly status: number;
readonly statusText: string;
readonly trailer: Promise<Headers>;
readonly type: ResponseType;
readonly url: string;
clone(): Response;
}
Check out mixins here for more clarification.
- A straightforward practical implementation
export default async function FetcherExample(
fetch: FetcherAbstracted
) {
const exactPath = 'docs/handbook/mixins.html';
const data: Response = await new fetch().fetcher(
`https://typescriptlang.org${exactPath}`,
{
body: exactPath,
method: 'GET',
headers: {
'Content-Type': 'application/json'
// ...
},
credentials: "include"
}
);
return await data.json();
}
Bringing it all together now in one code snippet for clarity
export type FetcherConstructor<T = {}> = new (...args: any[]) => T;
export type FetcherAbstracted = FetcherConstructor<{
fetcher: (url: string, init?: RequestInit) => Promise<Response>;
}>;
export default async function FetcherExample(
fetch: FetcherAbstracted
) {
const exactPath = 'docs/handbook/mixins.html';
const data: Response = await new fetch().fetcher(
`https://typescriptlang.org${exactPath}`,
{
body: exactPath,
method: 'GET',
headers: {
'Content-Type': 'application/json'
// ...
},
credentials: "include"
}
);
return await data.json();
}
UPDATE
To answer your question concisely, this hook should work with axios+SWR, which is similar to the parameter-constrained generic I wrote out above
type FetcherAbstracted = FetcherConstructor<{
fetcher: (url: string, init?: RequestInit) => Promise<Response>;
}>;
So much so you could use it for your Axios fetcher implementation.
const fetcher: FetcherAbstracted = async (url: string) => {
try {
const res = await Axios.get(url);
return res.data;
} catch (error) {
throw error.response.data;
}
};