我正在尝试编写一个钩子(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]
的类型而不是联合类型?
谢谢。
最佳答案
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
:是一个柯里化(Currying)函数。它需要我们感兴趣的对象元组,并返回需要 FilterBuilder
结果数组的函数。 FilterBuilder
仅返回 key/customFilter
对象所有允许状态的可区分联合。
关于Typescript - 当传入多个键值时缩小函数中的 T[K],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63708358/