Home > Back-end >  Property does not exist on type void
Property does not exist on type void

Time:12-29

I am writing a hook to make a post request that returns two properties, sessionId and sessionData. I am using this hook in a component. My hook looks like this.

export const createOrder = async () => {
  try {
    const response = await postWithToken(API_ROUTES.PAYMENT_SESSION, token || '', 
    testObject)
    console.log("FROM HOOK", response)
    return response
    } catch (err: any) {
      console.log(err)
    }
  }

And my component look like this

const myComponent = () => {
  useEffect(() => {
    createOrder().then(data => {
      console.log("Session Data",data.sessionData)
      console.log("FROM PAGE", data)
    })
  }, [])

  return (
    <div />
  )
}

When I try to access data.sessionData on the component I get the error that sessionDta does not exist on type void. But If I check the logs on the console I get the same object on the component and on the hook. Also If I check on my component the typeof data I get an object.

Why I am getting this error?

CodePudding user response:

You don't return anything from your catch block, so the return type of your function is Promise<WhateverTheTypeOfResponseIs | void> (N.B. async functions implicitly return a Promise, and if your postWithToken function doesn't return anything then it's just Promise<void>), depending on which code path happens.

In the future you can avoid unpleasant and slightly problematic to debug issues like this by giving your functions an explicit return type and in this case the compiler will let you know that your expectation was violated:

const postWithToken = async (route: string, token: string, obj: any): Promise<boolean> => {
  try {
    const resp = await fetch(
      route,
      { 
        method: 'POST',
        body: JSON.stringify(Object.assign(obj, { token }))
      },
    )
    return Boolean(resp.status < 400 && resp.status >= 200)
  } catch (err) {
    console.error(err)
    return false
  }
}

const API_ROUTES = {
    PAYMENT_SESSION: 'whatever'
}

const testObject = {
  token: ''
}

const token = ''

const createOrder = async (): Promise<boolean> => { // <-- squiggles
  try {
    const response = await postWithToken(API_ROUTES.PAYMENT_SESSION, token || '', 
    testObject)
    console.log("FROM HOOK", response)
    return response
  } catch (err: any) {
    console.log(err)
  }
}

Playground

The types in the example I created may be different (you'll need to sub with the actual types from your code) but you should get the idea. You can fix this by any of the following:

  1. Explicitly return something of the correct type from the catch block.
  2. Change your return type to Promise<CorrectType | undefined>.
  3. Move the error handling to the caller as suggested by goto1 in the comments.

Also note that as goto1 points out in the comments on the question, your hook isn't actually a hook (which is fine, but be careful of terminology).

CodePudding user response:

This sounds like a TypeScript issue, so I suggest to provide the proper return type for your createOrder function.

// Use the official type for SessionData, if you have it available,
// otherwise create a new type that properly matches its shape
type CreateOrderResult = {
  sessionData: SessionData;
}

// No need for `async/await` here, just return the `postWithToken`
// and handle errors inside your component
export const createOrder = (): Promise<CreateOrderResult> => {
  // ...
  return postWithToken(
    API_ROUTES.PAYMENT_SESSION, 
    token || '',
    testObject
  )
}

// MyComponent.tsx
const MyComponent = () => {
  useEffect(() => {
    createOrder()
      .then(data => console.log(data.sessionData))
      .catch(error => /* handle errors appropriately */)
  }, [])
}
  • Related