Home > front end >  Type assertion for promises with multiple return types
Type assertion for promises with multiple return types

Time:06-07

I've been having trouble using type assertions with multiple promise return types. Here's a stripped down version of the code:

interface SimpleResponseType {
   key1: string
};

interface SimpleResponseType2 {
   property1: string
   property2: number 
};

interface ServiceType {
   fetchResponse: () => Promise<SimpleResponseType | SimpleResponseType2> 
};

class Service implements ServiceType {
   async fetchResponse() {
      // code to fetch some api data and return some json
      // just return a pretend/sample response 
      return { key1: 'json' };
   };
};

const service = new Service();

await service.fetchResponse().then(resp => {
   // Should be typeof SimpleResponseType
   console.log(resp.key1)
})

TypeScript will underline the last key1 and throw this error:

Property 'key1' does not exist on type 'SimpleResponseType2'.ts(2339)

Which makes sense, but when I attempt to assert the type more errors show up. For example asserting it like this:

await service.fetchResponse().then((resp as SimpleResponseType) => {

It throws this err:

Argument of type 'SimpleResponseType' is not assignable to parameter of type '(value: SimpleResponseType | SimpleResponseType2) => SimpleResponseType | SimpleResponseType2 | PromiseLike<...>'.
Type 'SimpleResponseType' provides no match for the signature '(value: SimpleResponseType | SimpleResponseType2): SimpleResponseType | SimpleResponseType2

The only assertion I can get working is like this:

const respTyped = resp as SimpleResponseType

And then use respTyped instead of resp.

Maybe there's a better way to accomplish this?

CodePudding user response:

return { key1 = 'json' };

It looks like you are doing something strange. What if you type:

return { key1: 'json' };

CodePudding user response:

You could potentially use overloads. But you would need to have different input parameters on the function. I don't know your specific case but it seems a bit odd that there could be two different return types for the same exact API/function call.

CodePudding user response:

It's not entirely clear what you're aiming to achieve but perhaps this is what you're aiming for. Strongly typing your Service type so that you know the precise response type.

interface SimpleResponseType {
   key1: string
};

interface SimpleResponseType2 {
   property1: string
   property2: number 
};

interface ServiceType<T extends SimpleResponseType | SimpleResponseType2> {
   fetchResponse: () => Promise<T> 
};

class Service implements ServiceType<SimpleResponseType> {
   async fetchResponse() {
      // code to fetch some api data and return some json
      // just return a pretend/sample response 
      return { key1: 'json' };
   };
};

const service = new Service();
export {}
await service.fetchResponse().then(resp => {
   // Should be typeof SimpleResponseType
   console.log(resp.key1)
})
  • Related