0

I have a method defined that wraps fetch in order to automatically handle certain edge cases and provide a unified response class alerting system. I don't want to automatically parse responses as json (the platform will not only be requesting JSON) and came up with the idea to add to the fetch method's prototype a .json call to auto-parse and coerce the promise but found that I couldn't use the prototype when calling integratedFetch.json(//etc). Is is possible to add such a static method?

Example code:

const integratedFetch: (
    input: RequestInfo,
    init?: RequestInit | undefined,
    options?: Partial<IntegratedFetchOptions>
) => Promise<Response> = (input, init, options) => {
    return fetch(input, init).then(async (response) => {
        const { status } = response;
        const responseClass = getResponseClass(response);
        if (responseClass) {
            switch (Number(responseClass) as ResponseClass) {
                case ResponseClass.Informational:
                    //etc
                case ResponseClass.Successful:
                    //etc
                default:
                    throw Error(`Response class ${responseClass} unrecognized`);
            }
        }
        return Promise.resolve(response);
    });
};
integratedFetch.prototype.json = <T>(input: RequestInfo, init?: RequestInit | undefined, options?: Partial<IntegratedFetchOptions>) =>
    integratedFetch(input, init, options).then((response) => response.json() as Promise<T>);

With expected usage to be:

integratedFetch.json<MyType>(//request)
-vs-
integratedFetch(//request).then(r => r.json() as Promise<T>)

The current problem being that using integratedFetch.json() gives the error "Property 'json' does not exist on type '(input: RequestInfo, init?: RequestInit | undefined, options?: Partial | undefined) => Promise<...>'.ts(2339)"

2 Answers 2

1

Just assign the second function to a new property of the first function. Typescript keeps track of that. No adjust of the prototype is necessary.

const foo = () => 123
foo.bar = () => 'hello'

foo() // 123
foo.bar() // "hello"

See Playground

Sign up to request clarification or add additional context in comments.

2 Comments

For me this results in Property 'json' does not exist on type '(input: RequestInfo, init?: RequestInit | undefined, options?: Partial<IntegratedFetchOptions> | undefined) => Promise<...>'.ts(2339)
This answer led me to the real issue which is that I had explicitly defined the function type and needed to create an aggregate type that included both definitions - thanks!
0

Turns out I had to be a little more inventive with typedefs here...

type FetchParams = (input: RequestInfo, init?: RequestInit | undefined, options?: Partial<IntegratedFetchOptions>) => Promise<Response>;
type StaticParams = <T>(input: RequestInfo, init?: RequestInit | undefined, options?: Partial<IntegratedFetchOptions>) => Promise<T>;

//Create an aggregate typedef which allows for the static methods on the object definition
type IntegratedFetch = FetchParams & { json: StaticParams };

const integratedFetch: IntegratedFetch = (input, init, options) => { //the previous implementation


integratedFetch.json = <T>(input: RequestInfo, init?: RequestInit | undefined, options?: Partial<IntegratedFetchOptions>) =>
    integratedFetch(input, init, options).then((response) => response.json() as Promise<T>);

This avoids the TS2339 error and allows me to use the static method assigned to the function definition!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.