[英]TypeScript type discriminated unions in function arguments
[英]Typescript extract exact Discriminated conditional unions type in iterator method
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 過濾掉。
如何輸入第三個參數comparer:any
來自FILTER_META
類型的第一個參數
Stackblitz 鏈接https://stackblitz.com/edit/typescript-ku6bq7
switch(theValue)
中的值必須與您要嵌套的變量相同(即theValue.filters.id
)。 TypeScript 將知道當前theValue
的過濾器是“字符串”類型而不是“時間”類型,只是因為switch(theValue.type)
。 沒有它, (即您當前的代碼)TypeScript 無法知道id
是comparer
中的鍵,因為它不知道comparer
的類型是“字符串”、“時間”還是“范圍”。 這就是為什么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;
}
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.