Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function errors in typescript: has no properties in common with type 'Partial<PublicConfiguration<any, any, BareFetcher<any>>>' #2826

Open
angelod1as opened this issue Oct 30, 2023 · 10 comments

Comments

@angelod1as
Copy link

Bug report

Description / Observed Behavior

Updating the package, I have now some functions with typescript errors.

They throw Type '({ query, sessionToken, }: Data) => Promise<ApiResponse>' has no properties in common with type 'Partial<PublicConfiguration<any, any, BareFetcher<any>>>'.

I am certainly doing something wrong, as some other functions work properly.

See Repro Steps for more details.

Expected Behavior

The function should not error or the docs should be clearer on how to set the correct types.

Repro Steps / Code Example

const getInfo = async ({
  query,
  sessionToken,
}: Data) => {
  if (isNil(query.latitude) || isNil(query.longitude)) {
    return []
  }

  const request: HttpRequestParams = {
    method: "GET",
    path: route,
    query,
  }

  if (sessionToken) {
    request.headers = { [SESSION_TOKEN_HEADER_NAME]: sessionToken }
  }

  return performRequest<ApiResponse>(request)
}

// ...


  const { data, error, isValidating } = useSWR(
    shouldFetch ? { query, sessionToken } : null,
    getInfo,
    /* <--- TS error:
    No overload matches this call.
  The last overload gave the following error.
    Type '({ query, sessionToken, }: Data) => Promise<ApiResponse>' has no properties in common with type 'Partial<PublicConfiguration<any, any, BareFetcher<any>>>'.
    */
  )

I tried with no luck

  const { data, error, isValidating } = useSWR<ApiResponse>(
    shouldFetch ? { query, sessionToken } : null,
    getInfo,
  )

also::

const getNearestGarages: Fetcher<CoreApiGetRelevantGaragesResponse, Data> => ...

If I add the function straight into the hook, no error is thrown:

const { data, error, isValidating } = useSWR(
    shouldFetch ? { query, sessionToken } : null,
    async ({
      query,
      sessionToken,
    }) => {
      if (isNil(query.latitude) || isNil(query.longitude)) {
        return []
      }
    
      const request: HttpRequestParams = {
        method: "GET",
        path: route,
        query,
      }
    
      if (sessionToken) {
        request.headers = { [SESSION_TOKEN_HEADER_NAME]: sessionToken }
      }
    
      return performRequest<ApiResponse>(request)
    },
  )

If I cast the parameter as any it does not error anymore, e.g.:

const getNearestGarages = async ({ query, sessionToken }: any) => ...

If I simplify it also doesn't work:

async function getInfo(query: Query) {
  return performRequest<ApiResponse>({
    method: "GET",
    path: route,
    query,
  })
}

  const { data, error, isValidating } = useSWR(
    shouldFetch ? query : null,
    getInfo,
    // <--- same error
  )

Just as a comparison: this works perfectly in my codebase:

async function getInfo(query: Query) {
  return performRequest<ApiResponse>({
    method: "GET",
    path: ROUTES.api.core.vehicle.engine,
    query,
  })
}

  const { data, error } = useSWR(
    shouldFetch ? query : null,
    getInfo,
  )

Additional Context

SWR version: "swr": "^2.2.4"

@angelod1as
Copy link
Author

I've read through #939 and couldn't find an answer

@angelod1as
Copy link
Author

Weirdly, this stops the error... but... why!????

  const { data, error, isValidating } = useSWR(
    shouldFetch ? { query, sessionToken } : null,
    getInfo,
    {}, // <---- I added this
  )

@jarangutan
Copy link

jarangutan commented Nov 9, 2023

These two issues are related #2822

This started happening from release v2.2.3 from the removal of a type in #2759. Adding this back to the SWRHook interface or reverting to a version before v2.2.3 address the type error you got.

link to interface removed

// type that was removed
  <Data = any, Error = any>(
    key: Key,
    fetcher: BareFetcher<Data> | null
  ): SWRResponse<Data, Error>

Adding something ({} or undefined) after the fetcher makes the type fall onto one of the other overloads found in the SWRHook interface.

LucJosin added a commit to LucJosin/hawbrary that referenced this issue Nov 9, 2023
@angelod1as
Copy link
Author

@jarangutan thanks for your input. That was the 'fix' I used, although it's far from a fix — before I had proper types for my response, now, if I add any types it throws the error, and if I use {} I have zero types...

@jarangutan
Copy link

Fully agree on it being far from a fix. My response was mostly to add context on where this goof started happening for others.

And interesting :o

I was getting one of the interfaces with SWRConfiguration<Data, Error, Fetcher<Data, SWRKey>> with my type added to it for the Response and Error whenever I added {} or undefined for the config partial after the fetcher. Are you saying you get no types if you add {} after the fetcher?

What typescript version are you using? I wonder if that's making a difference if you're getting no types adding the config.

@henryfung3a27
Copy link

tl; dr

type QUERY_KEY = {
  query: string;
  sessionToken: string;
}
// ...
const fetcher: Fetcher<Result, QUERY_KEY> = (key) => fetch(...)
// ...
const { data, error, isValidating } = useSWR(
  { query, sessionToken } as QUERY_KEY,    // <-- add the type assertion
  fetcher,
)

After adding type assertion, compiler stopped complaining and yarn build success.

Detail

I also faced this error when upgrading nodejs from v18.15.0 to v18.19.0. (yeah, I didn't touch my project). After that I ran yarn build which then emitted this error.

I noticed that it only shows error when the key is NOT a literal type (string for example). If it is an object like in the example, there's complaints.

Adding {} to the third argument of useSWR fixed the issue

That's because you are trying to let the compiler thinks that you are overloading one of its "mutants".

Try adding the as Type assertion to the key of the useSWR hook (the first argument). It fixes the error.

@angelod1as
Copy link
Author

This solves it, although I dislike type assertions.

@henryfung3a27
Copy link

Ikr, it used to "just works".

@wmitsuda
Copy link

IMHO, that solution sounds more like a workaround, not a proper solution.

I'd recommend leave it open.

@angelod1as angelod1as reopened this Jan 22, 2024
@DiegoBistro
Copy link

DiegoBistro commented Jan 27, 2024

The SRW documentation says to do this (but it doesn't work)

const { data: user } = useSWR(['/api/user', token], ([url, token]) => fetchWithToken(url, token))

While in reality in this way it works

const fetchUser = async (url: string, id: string) => await getUser(id);

const { data, error } = useSWR('/api/users/${userId}', () => fetchUser('/api/users/${userId}', userId) );

with many params:

const fetchUserWithParam = async (url: string, id: string, myParam: string) => await getUser(id, myParam);

const { data, error } = useSWR( [ '/api/users/${userId}', myParam ], () => fetchUserWithParam('/api/users/${userId}', userId, myParam ) );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants