Different ways to fulfill the extends type interface requirement in TypeScript

Hey there, I'm looking to create reusable hooks for API requests. Here's the code I have so far:

interface DataResponse<Data> {
  data: Data[];
}

export const useRequestInfiniteHooks = <T extends DataResponse<T>>() => {
  const url = "/lms/class/all";

  const result = apiRequest()
  const mappedData: T['data'] = mappingData()

  return {data: mappedData};
};

type ClassesResponse = {
  data: {
    id: string;
    title: string;
  }[];
  total: number;
};

const MantapComponent = () => {
  const { data } = useRequestInfiniteHooks<ClassesResponse>();
};

I want the data to contain the type that's passed to the generic call. It seems to be getting the type, but the hook call isn't satisfied.

Here's the error response I'm getting:

https://i.sstatic.net/uEwT4.png

Type 'ClassesResponse' does not satisfy the constraint 'DataResponse<ClassesResponse>'.
  Types of property 'data' are incompatible.
    Type '{ id: string; title: string; }[]' is not assignable to type 'ClassesResponse[]'.
      Type '{ id: string; title: string; }' is missing the following properties from type 'ClassesResponse': data, totalts(2344)
type ClassesResponse = {
    data: {
        id: string;
        title: string;
    }[];
    total: number;
}

What should I do to satisfy this hook call?

I've tried calling it like this, but I still get the error:

https://i.sstatic.net/q6pDz.png

Type 'DataResponse<ClassesResponse>' does not satisfy the constraint 'DataResponse<DataResponse<ClassesResponse>>'.
  Type 'ClassesResponse' is not assignable to type 'DataResponse<ClassesResponse>'.
    Types of property 'data' are incompatible.
      Type 'Class[]' is not assignable to type 'ClassesResponse[]'.
        Type 'Class' is missing the following properties from type 'ClassesResponse': data, totalts(2344)
type ClassesResponse = {
    data: Class[];
    total: number;
}

I have read the documentation here, but it only shows how to create the function with generics, not how to call it properly to match the type passed.

So, my question is, how can I satisfy that hook/function call?

Answer №1

You seem to have a self-referential (possibly infinite) generic constraint issue. It is important that your ClassesResponse class extends from DataResponse. Here is a potential solution:

interface IData {
  id: string
}

interface IDataResponse<IData> {
  data: IData[]
}

export const utilizeInfiniteRequestHooks = <T extends IDataResponse<IData>>() => {
  const url = "/lms/class/all"

  const result = apiRequest()
  const mappedData: T['data'] = mappingData()

  return { data: mappedData }
};

class ClassesResponse implements IDataResponse<Data> {
  data: Data[];
  total: number
}

class Data implements IData {
  id: string
  title: string
}

const AwesomeComponent = () => {
  const { data } = utilizeInfiniteRequestHooks<ClassesResponse>()
}

Answer №2

Utilize the concept of Indexed Access Types to find the data type associated with the generic type T.

It is important to note that the generic parameter for DataResponse is Data, not T.

interface DataResponse<Data> {
  data: Data[];
}

export const useRequestInfiniteHooks = <T extends DataResponse<T['data'][0]>>() => {
  const url = "/lms/class/all";
  return {data: {}};
};

type ClassesResponse = {
  data: {
    id: string;
    title: string;
  }[];
  total: number;
};

const AwesomeComponent = () => {
  const { data } = useRequestInfiniteHooks<ClassesResponse>();
};

TypeScript 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's complex objects involve a sophisticated and intricate structure in

Just starting out with TypeScript and I'm looking to build a class that describes an object with the following structure: name(string), Array{ "column-name": { "type":"value", " ...

You cannot assign void to a parameter expecting a function with no return value

I have been working on an angular application that was initially developed in Angular 2, then upgraded to versions 7 and 9, and now I'm attempting to migrate it to Angular 11. There is a function in my code that fetches the notification count for the ...

Exporting stylesheets in React allows developers to separate

I am trying to figure out how to create an external stylesheet using MaterialUI's 'makeStyles' and 'createStyles', similar to what can be done in React Native. I'm not sure where to start with this. export const useStyles = m ...

Unable to access 'export default class extends Vue' in the template

I've recently started using Vue.js with TypeScript, but I'm having trouble accessing values from outside the class. @Component({ name: 'SidebarItem', components: { SidebarItemLink } }) export default class extends ...

Ensuring uniqueness in an array using Typescript: allowing only one instance of a value

Is there a simple method to restrict an array to only contain one true value? For instance, if I have the following types: array: { value: boolean; label: string; }[]; I want to make sure that within this array, only one value can be set to t ...

Is there a way to restrict an array to only accept distinct string literals?

export interface IGUser { biography: string; id: string; ig_id: string; followers_count: number; follows_count: number; media_count: number; name: string; profile_picture_url: string; shopping_product_tag_eligibility: boolean; username: ...

Encountered an unexpected token error when executing karma-coverage in a project using TypeScript

I have been working on a simple Angular/Typescript project that includes 12 basic unit tests which all pass successfully. However, I am now looking to measure the code coverage of these tests. Despite trying different methods, I have not been able to achie ...

Dealing with multiple queryParams in Angular2: Best practices

Need help implementing a filtering mechanism in my new Angular2 app. Looking to filter a list of entries in an array based on around 20 properties. I've set up filters in one component and a list component as a child that is routed to. Initially, pas ...

invoking a method within an express route to retrieve and utilize middleware functions

For my project, I am working on a custom function to handle API request validation. Here is how it looks: export function validateBody(schema: string): (req: ExpressRequest, res: ExpressResponse, next: ExpressNextFunction) => void { return function ...

What is the most appropriate form to use, and what factors should be considered in determining

Incorporating generics in typescript allows me to create a generic function in the following manner: Choice 1 declare function foo1<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; } Alternatively, I have the option to omit the seco ...

Encountering issues when trying to combine Sequelize with TypeScript

As I attempted to transition my NodeJs application to TypeScript, I encountered issues with Sequelize. Upon attempting to implement the code from a website, an error occurred: This expression is not constructable. Type 'typeof import("/home/de ...

A guide to troubleshooting and resolving the elusive 500 Server Error in Next JS API

Currently, I am in the process of developing a chat bot using the innovative OPEN AI GPT 4 Model within NextJS. However, upon sending a POST request to http://localhost:3001/api/generate, I am faced with a Response displaying a status code of 500 along wit ...

Is there a method of converting React components into strings for manipulation?

In my React TypeScript project, I am utilizing a crucial library that contains a component which transforms text into SVG. Let's refer to this library component as <LibraryRenderer />. To enhance the functionality, I have enclosed this componen ...

What is the proper way to create an array of dynamically nested objects in TypeScript?

Consider the structure of an array : [ branch_a: { holidays: [] }, branch_b: { holidays: [] }, ] In this structure, branch_a, branch_b, and ... represent dynamic keys. How can this be properly declared in typescript? Here is an attempt: ty ...

Having trouble showing table data in Angular

My goal is to showcase data from a table created using Spring-Boot Below is my model.ts: export class Quiz1 { QuestionId?: any; Question?: string; OptionsA?: string; OptionsB?: string; OptionsC?: string; OptionsD?: string;} He ...

What is the best way to determine the specific type of a value that is part of a union type?

Utilizing @azure/msal-react and @azure/msal-browser for implementing authentication in a React project with Typescript. The issue arises when TypeScript identifies event.payload as type EventPayload, but does not allow checking the exact type (e.g. Authen ...

Tips for accessing the PR number in a Node.js GitHub Probot listening for the `pull_request` event

I've recently developed a GitHub probot application using nodejs and typescript. Currently, I have set up an event listener for the pull_request event. How can I extract the pr_number from the context object within the probot? The snippet below is fr ...

Tips for obtaining the class type of a list using Java reflection?

How can I retrieve the generic class of a local variable List or other List type, without using Field to access the generic class? The variable in question is not a member variable. The method I am looking for should look like this: public Class<?> ...

Access SCSS variable values in Angular HTML or TypeScript files

So, I've been looking into whether it's feasible to utilize the SCSS variable value within HTML or TS in Angular. For instance: Let's say I have a variable called $mdBreakpoint: 992px; stored inside the _variable.scss file. In my HTML cod ...

specifying a specific type in a declaration

In this scenario, my goal is to distinguish between different types when declaring a new type: type Schedule = { flag_active : boolean, } type Channel = { flag_archived : boolean } type CreateChangeLog = { from : null, to : Schedule | Channel } ty ...