如何在打字稿中满足扩展类型接口

时间:2021-07-10 07:20:21

标签: typescript generics interface typescript-types

嗨,我想为 api 请求制作可重用的钩子 这是我的代码:

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>();
};

我希望数据包含传递给泛型调用的类型,即 . 它确实已经获得了类型,但是当我调用这个钩子时它不满意。

这是错误响应

hook call

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;
}

我该怎么做才能满足这个钩子调用?

我试着这样称呼它,但仍然出现错误

enter image description here

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;
}

我已阅读此处的文档 https://www.typescriptlang.org/docs/handbook/2/generics.html

他们只告诉您如何使用泛型创建函数,但没有告诉您如何正确调用它以使其满足您传递的类型。

所以我的问题是如何满足钩子/函数调用?

2 个答案:

答案 0 :(得分:0)

您有一种自我参照(可能是无限的?)通用约束。您还需要使您的 ClassesResponseDataResponse 扩展。以下可以工作:

interface IData {
  id: string
}

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

export const useRequestInfiniteHooks = <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 MantapComponent = () => {
  const { data } = useRequestInfiniteHooks<ClassesResponse>()
}

答案 1 :(得分:0)

使用 Indexed Access Types 查找泛型类型 dataT 类型。

DataResponse 的泛型参数是 Data,而不是 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 MantapComponent = () => {
  const { data } = useRequestInfiniteHooks<ClassesResponse>();
};

TypeScript Playground