繁体   English   中英

TypeScript:约束泛型类型参数传递给 function

[英]TypeScript: Constrain generic type parameter passed to a function

我有以下通用界面( 完整的游乐场):

interface Fetcher<Params,Resp> {
  fetch(params: Params): Resp;
};

它用作 function 参数,并对其通用参数应用额外的约束:

function paginateWithSearch<Params extends (PaginationParams & SearchParams),
  Resp extends SomeItemsResp>(fetcher: Fetcher<Params, Resp>){
    //do something      
}

所有约束都用简单的对象表示,例如:

type SearchParams = {
    query: string
};

棘手的部分是我不能让这个约束在实践中真正起作用:

//sample implementation with SearchParams only
const searchFetcher: Fetcher<SearchParams, SomeItemsResp> = {
  fetch: function(): SomeItemsResp {
    throw new Error("Function not implemented.");
  }
}

//Should throw error but works ok - not extending PaginationParams
paginateWithSearch(searchFetcher);

我想出的唯一方法是用条件类型推断泛型参数并将它们手动传递给 function:

//now throws error if inferred manually
paginateWithSearch<FetcherParamsInfer<typeof searchFetcher>, FetcherRespInfer<typeof searchFetcher>>(
  searchFetcher
);

我应该遗漏一些东西,因为这似乎是一个简单的问题。

虽然它可能违反直觉,但它按预期工作。

请记住,回调并非强制使用所有提供的 arguments 或其数据:

declare function convertObjToString(obj: {
  toString: () => string;
}): void;

[new Date()].forEach(convertObjToString);
// Fine, even though it receives a Date with many more properties

因此,传递一个只接受SearchParams参数的searchFetcher是完全可以的,而它将接收一个PaginationParams & SearchParams (即一个 object 具有比此searchFetcher所需的更多属性)。

我们甚至可以传递一个完全不带参数的回调:

paginateWithSearch({
  fetch() { // No arg at all: okay
    return {
      items: []
    };
  }
});

当然,这意味着这个回调不使用任何提供的数据,因此必然会返回不相关的响应(例如这里是一个固定的空数组)。

在您的示例中,它将返回仅与搜索相关的内容,而忽略分页参数。

paginateWithSearch的调用者来传递一个对这种情况有意义的回调:它是否应该与分页和搜索相关,只与其中之一相关,或者没有。

但它不能使用需要分页和搜索以外的东西的回调:例如没有排序

paginateWithSearch({
  // Error: Property 'sorting' is missing in type 'PaginationParams & SearchParams' but required in type '{ sorting: string; }'.
  fetch(params: { sorting: string }) {
    return { items: [] };
  }
})

游乐场链接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM