泛型 - Typescript - 當函數中傳入多個鍵值時收窄 T[K] 類型
我正在嘗試編寫一個 hook,它接受一個對象的多個鍵,並根據當前應用的過濾條件篩選數據。所以,大致如下所示:
interface IFilterable<T,K extends keyof T & string>{
key: K;
customFilter?: (item: T[K], applied: T[K][]) => boolean
//The hook uses some default logic to filter if this function isn't available.
}
function useFilters<T,K extends keyof T & string>(data: T[], filters: IFilterable<T,K>[]): T[]{
//filter out the data, return new dataset.
}
問題在於,當傳入多個過濾器(IFilterable)時,customFilter 函數中的 item 和 applied 參數會變成鍵類型的聯合。或者,用程式碼表達就是...
useFilters(
[{a: 1, b: "bob"], {a: 2, b: "berry"}],
[{key: "a", customFilter: (item, applied) => {
//Wanted: item has the type number
//Reality: item has the type (string | number)
},
{key: "b", customFilter: (item, applied) => {
//Wanted: item has the type string.
//Reality: item has the type (string | number)
}
}]);
我已經透過將所有東西都輸入為 unknown(或 unknown[]),然後再創建封裝函數將它們轉回適當類型,來“解決”這個問題,但如果可能的話,我想整個過程都保持強類型。
那麼,在這種情況下,有沒有任何方法,當我傳入一個物件陣列,其中一個屬性是鍵,另一個屬性是一個接受 T[K] 的函數時,能夠將類型縮小到特定的 T[K] 類型,而不是聯合類型?
謝謝。
答案#1
更新 2021年9月17日
我做了我的作業。
考慮這個例子:
/**
* Obtain a union of all values of a dictionary
*/
type Values<T> = T[keyof T]
type FilterBuilder<T extends any[]> = Values<{
[Key in keyof T[number]]: {
key: Key,
customFilter: (item: T[number][Key], applied: T[number][Key][]) => void
}
}>
{
// type Test = {
// key: "a";
// customFilter: (item: 1, applied: 1[]) => void;
// } | {
// key: "b";
// customFilter: (item: "str", applied: "str"[]) => void;
// }
type Test = FilterBuilder<[{ a: 1, b: 'str' }]>
}
const withFilters = <
Item extends Record<PropertyKey, unknown>,
Items extends Item[],
>(data: [...Items]) => <
Filter extends FilterBuilder<Items>,
Filters extends Filter[],
>(filters: [...Filters]) => { }
const useFilters = withFilters([{ a: 1, b: "bob" }, { a: 2, b: "berry" }])
const result = useFilters(
[{
key: "a", customFilter: (item, applied) => { }
},
{
key: "b", customFilter: (item, applied) => { }
}]
);
對 TypeScript 來說,很難推斷物件的 key 並立即將此類型應用到同一物件的另一個屬性,至少在這種情況下是如此。
因此,我剛剛創建了一個包含所有允許的 key/customFilter 過濾器對的聯集。
遊樂場
Values - 建立字典資料結構中所有值的聯集
FilterBuilder:
- 對元組
T中存在的每個元素鍵進行迭代。 - 為迭代的鍵創建一個新對象,帶有
key和customFilter屬性。 - 其中
customFilter是一個有兩個參數的函數:item- 被迭代對象的值,applied- 被迭代對象值的陣列
withFilters:是一個柯里化函數。它期望一個我們感興趣的對象元組,並返回一個函數,該函數期望一個 FilterBuilder 結果的陣列。FilterBuilder 只是返回一個所有允許的 key/customFilter 對象狀態的區分聯合。
