簡體   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