打字稿提取物精确区分有条件工会在迭代法中类型

发布于 2025-01-29 18:41:19 字数 1911 浏览 2 评论 0原文

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进行过滤。

如何键入第三参数比较:任何 type filter_meta

stackblitz链接 的第一个参数 https://stackblitz.com/edit/depescript-ku6bq7

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))
        )
    );

The above is generic filter fn, which is trying to filter an array based on filter type.
Its provided with array of different filter, which uses the comparer fn to filter out.

How to type the 3rd argument comparer:any from the 1st argument of type FILTER_META

Stackblitz Link
https://stackblitz.com/edit/typescript-ku6bq7

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

離人涙 2025-02-05 18:41:19

switch(theValue)中的值 必须与您嵌套到(ie thevalue.filters.filters.id)中的变量相同。
Typescript将知道当前theValue的过滤器是“字符串”类型,而不是“时间”类型,仅仅是因为switch(thevalue.type)没有它,(即您当前的代码)Typescript不知道idcontrace>比较中的关键,因为它不知道<<<代码>比较是类型“字符串”,“时间”或“范围”的类型。这就是为什么comparer.id不是typescript-lim有效的原因,

例如,如果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;
    }
  }
};

The value in switch(theValue) must be the same variable as the one you're nesting into (i.e theValue.filters.id).
TypeScript will know that the current theValue's filters are of the "string" type and not the "time" type JUST because of the switch(theValue.type). Without it, (i.e your current code) TypeScript can't know that id is a key in comparer since it doesn't know whether comparer is of type "string", "time" or "range". That's why comparer.id is not TypeScript-ly valid

For example, if fo is explicitly:
(notice: .filters is not an array)

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")
};

then this works:

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;
    }
  }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文