1
votes

I am doing a simple fetch using Typescript in a Class, which should return a promise, then I want to get the JSON response from this fetch. However, no matter what change I make, the function is always returning a Promise<void | T> which is ruining the type checking in my code.

export class ApiHelper {
    constructor() {     }

    public FetchFromPortal<T>(xyz: string) {

    ------ Other less relevant code -----------

        return fetch(url, options)
            .then((response) => this.CheckStatus(response))
            .then((response) => this.ParseJSON<T>(response))
            .then((response) => { 
                console.log(response);
                return response;
            })
            .catch((error: Error) => { console.log(error) });
    }

    private CheckStatus(response : Response) : Promise<Response> {
        if (response.status >= 200 && response.status < 300) {
            return Promise.resolve(response);
        } else {
            let error = new Error(response.statusText);
            throw error;
        }
    }

    private ParseJSON<T>(response : Response) {
        return response.json() as Promise<T>;
    }
}

I'm then subsequently calling it like this:

let result = apiHelper.FetchFromPortal<T>(xyz);

According to Typescript, this is returning a Promise<void | T>. I've tried resolving the promise in the call like so:

let result = apiHelper.FetchFromPortal<T>(xyz).then(data => { return data });

Which should in theory resolve the Promise but this doesn't appear to be working.

Any reason why the promise isn't resolving to just the object?

2
"it's clearly the request object." --- it's impossible. Are you not confusing it with console.log(response);?zerkms
@zerkms It actually is. I had a rogue console.log and because of the asyncronous request I was misreading the order. It is a Pending Promise state at that point. I'll update my original question.Dandy
"but this doesn't appear to be working." --- what does this exactly mean? You cannot escape a promise. Once you're inside - you're doomed on using only a promise object.zerkms
@zerkms I'm not trying to escape it. I'm trying to resolve the promise and return the json object from the fetch. At the moment, no matter what I do, the Promise is always in a pending state.Dandy
The void in Promise<void | T> comes from your catch. If an error occurs, your code swallows it, effecting the void. That is, if there is an error, there is no resolved T value.cartant

2 Answers

5
votes

Any reason why the promise isn't resolving to just the object?

Here is the reason:

        })
        .catch((error: Error) => { console.log(error) });

When exception happens, this handler logs error to console and does not return anything. The compiler sees this and adds void union member to the return type.

2
votes

Any reason why the promise isn't resolving to just the object?

Yes, promise resolution happens on some kind of "asynchronous space", the call will always just return a promise. The result of the promise is just forwarded through the then() chain and never returned to the caller (because they are asynchronous).

But I think you can have the behavior you are expecting by using await:

let result = await apiHelper.FetchFromPortal<T>(xyz);