我有以下通用界面(完整的游樂場):
interface Fetcher<Params,Resp> {
fetch(params: Params): Resp;
};
它用作函式引數,并對其通用引數施加額外的約束:
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);
我想出的唯一方法是用條件型別推斷泛型引數并將它們手動傳遞給函式:
//now throws error if inferred manually
paginateWithSearch<FetcherParamsInfer<typeof searchFetcher>, FetcherRespInfer<typeof searchFetcher>>(
searchFetcher
);
我應該遺漏一些東西,因為這似乎是一個簡單的問題。
uj5u.com熱心網友回復:
雖然它可能違反直覺,但它按預期作業。
請記住,回呼并不強制使用所有提供的引數或其資料:
declare function convertObjToString(obj: {
toString: () => string;
}): void;
[new Date()].forEach(convertObjToString);
// Fine, even though it receives a Date with many more properties
因此,傳遞searchFetcher只接受SearchParams引數的 a 是完全可以的,而它將接收 a PaginationParams & SearchParams(即具有比 this 所需屬性更多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: [] };
}
})
游樂場鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/506770.html
