Using Typescript to pass inferred type to React's useCallback

Illustration:

function useFunction(fn) {
  return fn;
}

type Data = {
  '/person': { person: any },
  '/place': { place: any },
};

function useData<Path extends keyof Data>(
  path: Path,
  options: {
    callback?: (data: Data[Path]) => void,
  },
) {}

useData('/person', { callback: ({ person }) => null }); // ok
useData('/person', { callback: ({ place }) => null }); // Property 'place' does not exist on type '{ person: any; }'
useData('/person', { callback: useFunction(({ person }) => null) }); // ok
useData('/person', { callback: useFunction(({ place }) => null) }); // should have error

TS Playground: Link

In this scenario, when using useFunction, TypeScript was able to automatically infer the type of the callback's argument. However, if useFunction is not used, this inference is lost.

Surprisingly, by making the callback property compulsory, TypeScript can infer the type of the argument as shown below:

function useData<Path extends keyof Data>(
  path: Path,
  options: {
    callback: (data: Data[Path]) => void, // <- "?" removed
  },
) {}

useData('/person', { callback: useFunction(({ place }) => null) }); // Property 'place' does not exist on type '{ person: any; }'

How can TypeScript deduce the callback's argument type?

Answer №1

When using the optional operator ?, it is not important.

The Typescript parser is able to properly deduce the types.

If you specified the first parameter of the useApi function as '/user', it will not function correctly.

To make it work, update it to,

useApi('/post', { cb: useCallback(({ post }) => null) });

Then it will work correctly.

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

Check my Twitter feed every 10 seconds

I'm attempting to access my Twitter feed (sent from a smartphone) for a local application, as Twitter is remote... I created a jQuery + JSON script, but with my overly frequent setInterval at 25ms, I quickly hit the limit of 150 requests per hour and ...

Error message: "Reactjs - TypeError: The property 'map' cannot be read as it is undefined in the table"

I have encountered an issue while using the material-ui table. I am able to map the items and display them successfully, but when trying to map the orders.items in the table, I get the following error: TypeError: Cannot read property 'map' of u ...

Is the ID "nodeName" specifically designated as reserved in the HTML5 language specifications?

I have an element with the following id: <span id="nodeName"></span> In my HTML code. Then, when using jQuery to do the following: $("#nodeName").html("someString"); I am getting an error in the console that says: Uncaught TypeError: Objec ...

retrieve the most recent file following a $group operation

I am currently utilizing the official MongoDB driver specifically designed for Node.js. This is how my message data is organized. Each post consists of a timestamp, a user ID, and a topic ID. [ { "_id" : ObjectId("5b0abb48b20c1b4b92365145"), "t ...

Is there a way to efficiently execute an API function for every element within an array in a sequential manner?

I am currently facing a challenging problem while working with Angular and RxJs. I have an array containing several IDs: ids = [1,2,3,4] There is an API that can be called with a specific ID parameter to delete the corresponding item from the database: th ...

I wish for the value of one input field to always mirror the value of another input field

There is a checkbox available for selecting the billing address to be the same as the mailing address. If the checkbox is checked, both values will remain the same, even if one of them is changed. Currently, I have successfully achieved copying the mailing ...

Using Angular 4's ngComponentOutlet to showcase ContentChildren that are dynamically changing

My main objective is to create a unique container component with a dynamic list of customized card components that can be accessed individually (instead of as a group using ng-content). <custom-card-holder> <custom-card></custom-card> ...

Angular Square Grid Design

Attempting to create a square grid layout using CSS for ng-repeat items. Essentially, I am looking to have one big square followed by four smaller squares that combined have the same width and height as the big square. Here is my CSS: .container{ widt ...

Steps to retrieve component values within the same component

I am currently working on developing a React component where I need to manage the checked status of checkboxes and select options when a change event occurs. However, I am unsure of how to retrieve the value of the checked checkboxes and update the state a ...

Angular - Resolving the issue of 'property does not exist on type' in TypeScript

Currently, I am following a video tutorial which also has a text version. Despite copying the code exactly as shown in the tutorial, I encountered the following error: Error TS2339: Property 'getEmployees' does not exist on type 'Employ ...

"The interplay of Vue components: exploring the relationships, lifecycle hooks

Brand new to utilizing Vue.js. I am exploring the concept of having a single parent component and two child components that need to communicate asynchronously through Vue's event bus system. This involves using a dummy Vue object as a shared container ...

Clearing error messages from a form using the reset button or after cancelling the form

I am having trouble removing the error outline around the input box and error messages displayed below it. When I cancel the form or click on the reset button, the input fields' content along with the error messages should be cleared. However, current ...

Creating and implementing a HTML template from scratch, devoid of any frameworks

Is there a way to create a quiz where all questions follow the same format and only one question is displayed at a time, without duplicating code? Perhaps using a template would be the ideal solution in this scenario. I appreciate your help. ...

Retrieve the value of a variable to access an object property dynamically in React Native using TypeScript

As I attempted to create dynamic styles for this component, my goal was to determine the styles based on a string passed in as a property. Here is the code snippet: export type MyComponentProps = { styleName: string; } const MyComponent = (props: MyComp ...

A step-by-step guide on leveraging useRef() to specifically target dynamic material-ui tabs

When attempting to upload files to a specific channel, they always end up being uploaded to the first tab or channel. I've been using useRef to try and fix this issue, but I'm not sure what exactly is missing. By "tab," I am referring to the tab ...

What is the process for switching directories and renaming a file when uploading in nodeJs?

I am currently using multer and fs to handle the upload of an image file. How can I modify the directory where uploaded files are stored? Currently, all files are saved in my "routes" folder instead of the "uploads" folder created by multer. Additionally, ...

What is the best way to measure the loading time of a "Loading Screen" page using Jmeter and Selenium?

Once a file is uploaded to the website, a loading screen appears depending on the file size. I am interested in measuring how long this loading screen remains active. As a novice in jmeter and programming, I'm unsure if there's a more efficient m ...

Testing components in React Native using asynchronous Jest methods

I have a component that triggers a fetch request when it mounts and then displays the results. I've been struggling to create a test snapshot of this component after the request is completed. I've searched on various forums like SO but haven&apo ...

Is there a way to customize the animation for a button in material UI?

Trying to implement material UI in React and looking for a button that does not have the standard wave animation effect upon clicking, which you can see demonstrated here. Instead, I am searching for an animation that instantly fills the entire button wit ...

What is the best way to adjust the height and width of a div when it comes into view through scrolling?

How can I automatically and frequently change the size of my div when it is scrolled into view? HTML <div id="contact" class="fadeInBlock"> <div class="map"> <div class="pointer"> <div class="dot"></div& ...