Understanding how to infer the type of a function when it is passed as an argument

Looking at the images below, I am facing an issue with my function that accepts options in the form of an object where one of the arguments is a transform function. The problem is that while the type of the response argument is correctly inferred for the entire function (as seen in the first and second pictures), my TypeScript compiler implicitly treats the response argument as the any type (shown in the third picture). I'm confused about why it's not recognizing the proper response type which should be

ApiResponse<NewsListApiResponseData>
in this scenario.

https://i.stack.imgur.com/DSgzg.jpg https://i.stack.imgur.com/jrnGQ.jpg https://i.stack.imgur.com/0IenW.jpg

Error:(27, 20) TS7006: Parameter 'response' implicitly has an 'any' type.

Below is the definition of my overloaded useAxios hook for this situation:

export function useAxios<ResponseData, TransformedData = false | null | ResponseData>(
    endpoint: string,
    options: {
        autoStart?: boolean;
        transform: (response: ApiResponse<ResponseData>) => TransformedData;
        onResolve?: (data: TransformedData) => void;
        onReject?: (error: Error) => void;
    } & AxiosHookRequestConfig
): {
    loading: boolean;
    canceled: boolean;
    error?: Error;
    response?: AxiosResponse<ApiResponse<ResponseData>>;
    data?: TransformedData;
    request: (config?: AxiosHookRequestConfig) => Promise<TransformedData>;
    cancel: (reason?: string) => void;
};

Edit: Added AxiosHookRequestConfig definition.

export interface AxiosHookRequestConfig extends Omit<AxiosRequestConfig, 'url' | 'cancelToken'> {
    page?: number;
    lang?: string;
    cache?: boolean | string;
}

... // The rest of the code remains the same.

Edit2: Example

Answer №1

Let's delve into the heart of this matter:

function foo<T>(x: { prop: T }): void;
function foo<T>(x: { prop: T, func: (x: T) => void }): void;
foo({ prop: "hey", func: x => x.length }); // error!
//   ┌─────────────────> ~
// Parameter 'x' implicitly has an 'any' type.

This scenario mirrors this reported issue, deemed as "working as intended". The issue arises when the call corresponds to the first overload signature, leaving the compiler unable to infer the type of x.

How does it fit both signatures? The reason is that in TypeScript, object types are not exact. If you have an interface like interface Foo {a: string}, and another interface

interface Bar extends Foo {b: string}
, every instance of Bar is also a Foo due to subtyping rules. Therefore, a type like {a: string} is compatible with any object having additional properties, as long as it contains a string-valued property named a. The compiler usually provides warnings about excess properties but seems to overlook them in this case since func is part of the types being checked which may be a design limitation or a bug.

Subsequently, the compiler perceives func as a function type, yet fails to operate with contextual typing for x when matching the first overload, resulting in the "implicit any" error message.


Several approaches can be taken from here. One option is to rearrange the order of overloads so that the first one is more restrictive. Overload resolution halts at a generic top overload signature preventing further processing. Hence, a good practice is to place more specialized overloads above general ones:

function foo<T>(x: { prop: T, func: (x: T) => void }): void;
function foo<T>(x: { prop: T }): void;
foo({ prop: "hey", func: x => x.length }); // okay

This selection chooses the first overload, where the data type of func is known, allowing x to be inferred as string.


Another approach involves modifying the more-general overload to disallow the concerned call by making func a property that cannot exist, like so:

function foo<T>(x: { prop: T, func?: never }): void;
function foo<T>(x: { prop: T, func: (x: T) => void }): void;
foo({ prop: "hey", func: x => x.length }); // okay

With this alteration, in the initial overload, func becomes an optional property with a value of type never. Except for undefined, there is no other way to satisfy the condition, making a function like x => x.length invalid. Hence, the call bypasses the first overload to choose the second and infers string for x.


Lastly, if two similar overloads differ only in a potentially present property, merging them into a single signature without overloads might be beneficial. Although this may not align with your specific requirements, it is something worth considering:

function foo<T>(x: { prop: T, func?: (x: T) => void }): void;
foo({ prop: "hey", func: x => x.length }); // okay

Now, there exists a lone call signature allowing func to be either present or absent.


You can explore these options to find a suitable solution. Wishing you the best of luck!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best approach for managing and obtaining accurate JSON responses when working with PHP API and AngularJS 2 services?

Encountering a backend issue with MySQL, wherein one query is producing a specific dataset: {"candidat":[{"ID":1,"nom":"Danny","prenom":"Hariot","parti":"Quamba","departement":"Ukraine","commune":"Chapayeve"},{"ID":2,"nom":"Shari","prenom":"Adamkiewicz"," ...

How to properly display an Angular Template expression in an Angular HTML Component Template without any issues?

When writing documentation within an Angular App, is there a way to prevent code from executing and instead display it as regular text? {{ date | date :'short'}} Many sources suggest using a span element to achieve this: <span class="pun"&g ...

How can Angular2 detect when an entity is clicked within a window?

There are multiple items generated using *ngFor: <my-item *ngFor="let item of myArray" [p]="item"></my-item> I am able to handle a click event like this: <my-item ... (click)="doWork(item)"></my-item> However, I want to avoid a ...

Creating a React website and running it locally on VSCode

Hey there! I'm currently facing some difficulties running this repository on my local machine. Can someone lend a hand? Check it out here! When trying to execute "npm run dev", I encounter the following errors: ⨯ ../../node_modules/next/dist/build/ ...

Encounter the "Error: Source 'cloudsTileLayer-RasterSource' not found" message while trying to integrate a weather tile layer into Azure Maps

I have been working on a React application that utilizes the React-Azure-Maps npm package. My current challenge involves creating a weather layer, which I believe shares similarities with the sample code provided for layers. The code snippet responsible f ...

Expanding the boundary with Material-UI: Tips for stretching the margin

I am currently working on creating a navigation bar using Material UI, and the current layout can be seen in the image below. https://i.stack.imgur.com/AOy3v.png While following the template provided by MUI documentation, I encountered an issue with alig ...

Render function in Next.js did not yield anything

Recently, I came across the next.js technology and encountered an error. Can anyone help me solve this issue? What could be causing it?View image here import React from 'react' import Button from "../components/button" function HomePa ...

What are the best practices for implementing optional chaining in object data while using JavaScript?

In my current project, I am extracting singlePost data from Redux and converting it into an array using Object.keys method. The issue arises when the rendering process is ongoing because the singlePost data is received with a delay. As a result, the initi ...

Navigating through a collection of images with Next Js using button clicks

I'm currently working on a project that involves looping through a folder of six images when the user clicks the "update profile picture" button. I've encountered some challenges with props in Next Js and would greatly appreciate any assistance. ...

Retrieve the route parameters and exhibit the default option in a dropdown menu using Angular 2/4/5, along with translations implemented through ngx-translate

Is there a way to extract route parameters from a URL and then display them in a drop-down menu? I've attempted some solutions using ActivatedRoute, but they are not returning the first value after the base reference. For instance, If the URL is: l ...

Postgres Array intersection: finding elements common to two arrays

I'm currently developing a search function based on tags, within a table structure like this CREATE TABLE permission ( id serial primary key, tags varchar(255)[], ); After adding a row with the tags "artist" and "default," I aim ...

Struggling with React integration of AdminLTE3 sidebar treeview?

I have a requirement to create a React sidebar with a category 'Staff' that, when clicked, reveals three subordinate categories. Below is the code snippet: import React, { Component } from "react"; export default class Sidebar extends Componen ...

How can I implement a feature to automatically close a drawer in a React application using the Material UI

Currently, I am utilizing a React material design theme However, I am facing an issue where the drawer navigation button on mobile view does not close automatically upon clicking I need something like (onClick={handleClose}) to resolve this problem Does ...

Navigating in React: A Guide to Switching Components

I'm currently working on a landing page project using React. The goal is to have a consistent navigation bar across all sections of the website, with only the active state changing based on user interaction. Within my App.js file, I've implement ...

Leverage Sinon's fakeServer in combination with promises and mocha for efficient

Having an issue here: I need to test a method that involves uploading data to an AWS S3 bucket. However, I don't want the hassle of actually uploading data each time I run my tests or dealing with credentials in the environment settings. That's w ...

Importing CSS properties from MUI v5 - A comprehensive guide

I'm working with several components that receive styles as props, such as: import { CSSProperties } from '@material-ui/styles/withStyles' // using mui v4 import because unsure how to import from v5 paths import { styled } from '@mui/mat ...

Creating a Drop-Down Button Using HTML, CSS, and JavaScript

I am currently working with the following code: <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=PT+Sans ...

I am facing an issue with my Angular 11 CLI application while trying to set it up with Jest. The specific error message I am encountering is: "TypeError: Cannot read property

Having issues with my Angular 11 cli app and Jest integration. Whenever I run npm run test, specifically jest --updateSnapshot, I encounter the following error in my terminal: Error: TypeError: Cannot read property 'paths' of undefined Here is ...

What could be the reason for receiving an undefined user ID when trying to pass it through my URL?

Currently, I am in the process of constructing a profile page and aiming to display authenticated user data on it. The API call functions correctly with the user's ID, and manually entering the ID into the URL on the front end also works. However, wh ...

What is the best way to access a value within a JSON object in a React render method?

Overview I am currently working on creating a blog using React and JSON data. Upon checking this.state.blogs, I am getting the output of: [object Object],[object Object],[object Object]. I have attempted to use the .map function but I am not sure how to ...