Ensure that you accurately input the arguments for the callback function according to the data types of the elements in the

I'm facing a challenge in TypeScript.

Essentially, I am attempting to replicate the functionality of useSWR. In useSWR, you can pass an array of arguments as the first parameter in a function, and then provide a callback function as the second parameter where the elements of the array become the arguments for the callback.

For instance:

const fetcher = async(arg1: string, arg2: string): Promise<string | boolean> => {
    try {
        return arg1 + ' - ' + arg2
    } catch(e) {
        return false
    }
}

type Fetcher<T, A extends any[]> = (...args: A) => Promise<T>

const useAdminEndpoint = <T, A extends any[]>(key: A, fetcher: Fetcher<T, A>) => {
    const run = async() => {
        try {
            return await fetcher.apply(null,key)
        } catch(e) {
            return false
        }
    }
    return result
}

const result = useAdminEndpoint(['hello',2],(h,g) => fetcher(h,g))

The parameter types represent the types of the items within the array as a tuple, rather than mapping them to specific variables like arg0 = array[0], arg1 = array[1], and so on.

I'm unsure about the terminology for what I'm attempting to achieve here, making it difficult to search for solutions. Is it feasible to have the order of arguments infer their respective type from the items in the array?

Answer №1

The issue arises when the type of passed array arguments is widened to a generic type. For example:

const arr = ['hello', 1];
// (string | number)[]
type Arr = typeof arr;

This widening of types also occurs in your function call. To address this, you can use const assertion, which prevents the compiler from broadening the type by declaring the array as readonly:

const arr = ['hello', 1] as const;
// readonly ["hello", 1]
type Arr = typeof arr;

In terms of improving the function, with typescript 5.0, const type parameters were introduced, serving the same purpose as const assertion. This eliminates the need for adding as const repeatedly:

type Fetcher<T, A extends readonly any[]> = (...args: A) => Promise<T>;

const useAdminEndpoint = <T,const A extends readonly any[]>(
  key: A,
  fetcher: Fetcher<T, A>,
) => {
  const run = async () => {
    try {
      return await fetcher(...key);
    } catch (e) {
      return false;
    }
  };
  return run();
};

By utilizing const assertion and const type parameters, which turn arrays into readonly, we update the conditions accordingly (any[] -> readonly any[])

Test examples:

const result = useAdminEndpoint(['hello', 'world'], (h, g) => fetcher(h, g));
const result2 = useAdminEndpoint(['hello', 2], (h, g) => fetcher(h, g)); // expected error - argument 2 should be a string

playground

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

typescript What is the best approach to searching within a nested array?

I am struggling to extract a specific value from a nested array within an array. Here is an example structure of my array: [ { ConcessionId: 1, ConcessionName: "Coyotes", KnownAs: [ { TeamId: 1, ...

Ways to disperse items within another item

I have an inner object nested inside another object, and I am looking to extract the values from the inner object for easier access using its id. My Object Resolver [ { _id: { _id: '123456789', totaloutcome: 'DONE' }, count: 4 }, { ...

Unable to attach to 'leafletOptions' as it is unrecognized as a property of 'div'

It seems like I keep encountering this problem, which is often resolved by adjusting import statements. Right now, my imports look like this: import { LeafletModule } from 'node_modules/@asymmetrik/ngx-leaflet'; import * as L from 'leaflet& ...

Is it no longer possible to instantiate an object using the syntax <interface>{}?

There seems to be an issue with the code snippet below when run in the TypeScript playground: interface Person { name: string; age: number; } const makePerson= function(name : string, age : number) : Person { let obj = <Person>{} ...

"Error: Unable to locate module - 'electron-is-dev'" in my web development project using electron, typescript, and webpack

I'm currently working on a project using Electron, Typescript, and webpack. I am planning to integrate react.js into the project. However, when I ran "npx webpack" in the terminal, I encountered an error message. The error stated that the "electron- ...

Steps to create a personalized loading screen using Angular

I am looking to enhance the loading screen for our angular 9 application. Currently, we are utilizing <div [ngClass]="isLoading ? 'loading' : ''> in each component along with the isloading: boolean variable. Whenever an API ...

Issue with dispatching actions in React using TypeScript and hooks

Can you please point out what I'm doing wrong here: I am encountering the following error Type '{ wishList: any; addBookToWishList: (book: any) => void; }' is not assignable to type '{ wishList: never[]; }'. Object literal may ...

What is the best way to implement React ErrorBoundary in conjunction with redux-observable?

When dealing with asynchronous code, React Error Boundaries may not function as expected. In my case, I am using redux-observable and rxjs to retrieve data from an API. To handle errors, I am trying to utilize the catchError function provided by rxjs. I ...

Encountering Issues with TypeScript Strict in Visual Studio Code Problems Panel

I have discovered that I can optimize my TypeScript compilation process by utilizing the --strict flag, which enhances type checking and more. Typically, I compile my TypeScript code directly from Visual Studio Code with a specific task that displays the c ...

Creating a structure within a stencil web component

In my current project, I am utilizing Stencil.js (typescript) and need to integrate this selectbox. Below is the code snippet: import { Component, h, JSX, Prop, Element } from '@stencil/core'; import Selectr from 'mobius1-selectr'; @ ...

Error in Ionic 3: "this is null"

Whenever I fetch data from Firebase, I am attempting to redirect accordingly. If the data is null or empty, then there is no need for redirection. My attempt involves using this.navCtrl.push(ProspectPage); but for some reason, it is not functioning proper ...

Once the vuex persist plugin is implemented, I am encountering difficulties in accessing the store within the router

Ever since incorporating the vuex persist plugin, I've been encountering an issue where the store doesn't seem to be accessible in the router. const vuexPersist = new VuexPersist({ key: "vuex", storage: localStorage }); const store = ne ...

The property of the Angular Typescript object is distinctly not defined, yet the property itself is

Currently facing a bizarre issue. Even though the console displays data in an object from a subscribed observable, TypeScript code shows it as undefined. Take a look: initData(): void { this.backendService.getData().subscribe((depotDays: DepotDayAcc ...

Converting information from a model into individual variables

I'm a newcomer to typescript and angular, and I've been attempting to retrieve data from firebase using angularfire2. I want to assign this data to variables for use in other functions later on. I am accustomed to accessing object members using d ...

Distributing utility functions universally throughout the entire React application

Is there a way to create global functions in React that can be imported into one file and shared across all pages? Currently, I have to import helper.tsx into each individual file where I want to use them. For example, the helper.tsx file exports functio ...

How to utilize TypeScript fetch in a TypeScript project running on node with Hardhat?

During a test in my hardhat project on VSCode, I encountered the need to retrieve the metadata object of my NFT from a specified URL. Initially, I assumed I would have to import fs to read the URL. However, while typing out the method, I impulsively opted ...

Can type safety be maintained while utilizing generics in code?

Suppose I have multiple classes with a similar method for saving models. For example, many services that include a saveModel method: public async saveModel(newModel: IModel): Promise<IModel> { return await newModel.save(); } I created a generic ...

Typescript error message TS2693: The identifier 'Note' is used as a value although it refers to a type

I have been attempting to incorporate Typescript into my Firebase project, but unfortunately I am encountering the following errors: error TS2693: 'Note' only refers to a type, but is being used as a value here. The code snippet I used is as fo ...

Interface of TypeScript Undetermined

Currently, I am developing a Demo API Wrapper specifically for Roblox. During the development process, I have come across a certain issue that I would like to address. My aim is to send a request and then return all the data in the manner of an API wrapper ...

Something went wrong: the element type is not recognized. Instead of a string or class/function, it appears to be undefined. Import error detected

I encountered the following error: Error: Element type is invalid. Expected a string (for built-in components) or a class/function (for composite components) but received: undefined. This could be due to forgetting to export your component from the file ...