export type FILTER_META =
| {
type: 'string';
key: string;
filters: { id: string; label?: string }[];
}
| {
type: 'time';
key: string;
filters: { min: string; max: string }[];
}
| {
type: 'range';
key: string;
filters: { min: number; max: number }[];
};
type Unpacked<T> = T extends (infer U)[] ? U : T;
type Foo = Unpacked<FILTER_META['filters']>;
// how to determine comparer type from meta object
// comparer:Foo doesn't work
// const comparator = <T extends FILTER_META, U extends Unpacked<T['filters']>>(
const comparator = (meta: FILTER_META, item: any, comparer: any) => {
const DATE_PREFIX = '1/1/2022 ';
switch (meta.type) {
case 'string':
return item?.[meta.key]?.toLowerCase() === comparer.id?.toLowerCase();
case 'time': {
const { min, max } = comparer;
const compTime = new Date(DATE_PREFIX + item?.[meta.key]);
return (
new Date(DATE_PREFIX + min) <= compTime &&
compTime <= new Date(DATE_PREFIX + max)
);
}
case 'range': {
const { min, max } = comparer;
const compItem = item?.[meta.key];
return min <= compItem && compItem <= max;
}
}
};
const genericFilter =
(filterMeta: FILTER_META[]) =>
(list = []) =>
list.filter((item) =>
filterMeta
.filter((fMeta) => fMeta.filters.length)
.every((meta) =>
meta.filters.some((ft: any) => comparator(meta, item, ft))
)
);
上面是通用过滤器fn,它试图根据过滤器类型过滤数组。它提供了一个不同过滤器的数组,它使用比较器fn来过滤。
如何从类型为FILTER_META
的第一个参数中输入第三个参数comparer:any
Stackblitz链接https://stackblitz.com/edit/typescript-ku6bq7
switch(theValue)
中的值必须是相同的变量作为你正在嵌套的(即theValue.filters.id
)。TypeScript会知道当前theValue
的过滤器是"string"键入而不是"时间"。因为switch(theValue.type)
。,(即你当前的代码)TypeScript不能知道id
是comparer
中的一个键,因为它不知道comparer
的类型是否为"string", "time"或";range"。这就是为什么comparer.id
不是typescript有效的
例如,如果fo
显式为:(注意:.filters
是而不是)一个数组)
type fo = {
type: 'string';
key: string;
filters: { id: string; label?: string }; // not an array (is unpacked")
}
| {
type: 'time';
key: string;
filters: { min: string; max: string }; // not an array (is "unpacked")
}
| {
type: 'range';
key: string;
filters: { min: number; max: number }; // not an array (is "unpacked")
};
const comparator = (meta: FILTER_META, item: any, comparer: fo) => {
const DATE_PREFIX = '1/1/2022 ';
switch (comparer.type) {
case 'string':
return item?.[meta.key]?.toLowerCase() === comparer.filters.id?.toLowerCase();
case 'time': {
const { min, max } = comparer.filters;
const compTime = new Date(DATE_PREFIX + item?.[meta.key]);
return (
new Date(DATE_PREFIX + min) <= compTime &&
compTime <= new Date(DATE_PREFIX + max)
);
}
case 'range': {
const { min, max } = comparer.filters;
const compItem = item?.[meta.key];
return min <= compItem && compItem <= max;
}
}
};