Home > Software design >  Typescript add static method to a method
Typescript add static method to a method

Time:11-22

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)"

CodePudding user response:

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

CodePudding user response:

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>;

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!

  • Related